<?php

/**
 * 库存service层
 */

namespace app\admin\service;

use app\admin\model\InventoryChangeRecord;
use app\admin\model\Operator as OperatorModel;
use app\admin\model\OrderItem as OrderItemModel;
use app\admin\model\PurchaseOrders;
use app\admin\model\PurchaseOrdersDetail;
use app\admin\model\PurchaseReceiptDetails;
use app\admin\model\Warehouse as WarehouseModel;
use app\admin\model\OrderItem;
use app\admin\model\ProductDiscount as ProductDiscountModel;
use app\admin\model\WholesalOrderItem;
use app\api\model\LogisticsOrderItem;
use app\api\model\Order as ModelOrder;
use app\api\model\WholesalOrder;
use app\common\ExcelService;
use think\facade\Db;
use app\admin\model\Inventory as InventoryModel;
use app\admin\model\TransactionCurrency as TransactionCurrencyModel;
use app\admin\model\ProductPrice as ProductPriceModel;
use app\admin\model\Product as ProductModel;
use \Exception;
use app\common\ExchangeRateHostAPI;
use app\admin\logic\Inventory as InventoryLogic;
use app\common\service\Inventory as InventoryService;
use app\common\service\Mail;
use think\facade\Log;
use app\common\RedisClient;
use app\common\service\CompleteNotificationService;
use think\facade\Config;
use app\admin\logic\Inventory\InventoryTransSave;

class Inventory extends BaseService
{

    /**
     * 获取库存列表
     * @param $param
     * @param $page
     * @param $limit
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getList($param = [], $page = 1, $limit = 10)
    {
        $arrData = ['code' => 0, 'message' => 'success'];
        $inventoryWhere = [['db_inventory.is_del', '=', 0]];
        if ($param['is_futures'] != null) {
            $inventoryWhere[] = ['is_futures', '=', $param['is_futures']];
        }
        if ($param['is_sale'] != null) {
            $inventoryWhere[] = ['is_sale', '=', $param['is_sale']];
        }
        if ($param['if_tlz'] != null) {
            $inventoryWhere[] = ['if_tlz', '=', $param['if_tlz']];
        }
        if ($param['allow_zero_stock_sale'] != null) {
            $inventoryWhere[] = ['allow_zero_stock_sale', '=', $param['allow_zero_stock_sale']];
        }
        if ($param['arrival_date']) {
            $arrival_date = explode(',', $param['arrival_date']);
            $inventoryWhere[] = ['arrival_date', 'between', $arrival_date];
        }
        if ($param['real_arrival_date']) {
            $real_arrival_date = explode(',', $param['real_arrival_date']);
            $inventoryWhere[] = ['real_arrival_date', 'between', $real_arrival_date];
        }
        if ($param['source_table']) {
            $inventoryWhere[] = ['source_table', '=', $param['source_table']];
        }
        $productWhere = [];
        if (isset($param['name']) && $param['name']) {
            $productWhere[] = ['cname', 'like', '%' . trim($param['name']) . '%'];
        }

        $field = [
            'i.id',
            'i.arrival_date',
            'i.real_arrival_date',
            'i.available_qty',
            'i.convertible_qty',
            'i.allow_zero_stock_sale',
            'i.create_time',
            'i.creator',
            'p.hashrate',
            'i.inbound_batch',
            'i.initial_qty',
            'i.is_del',
            'i.is_futures',
            'i.is_sale',
            'last_audit_date',
            'i.lock_qty',
            '(i.available_qty - i.lock_qty) as actual_available_qty',
            'p.cname as product_name',
            'i.productid',
            'i.remark as notes',
            'sku',
            'source_id',
            'source_table',
            'i.source_table',
            'i.updater',
            'i.update_time',
            'i.wid',
            'freight_price'
        ];
        $model = Db::table('db_inventory')
            ->alias('i')
            ->field($field)
            ->join('db_product p', 'i.productid = p.id')
            ->where($inventoryWhere)
            ->where(function ($query) {
                $query->where(function ($query) {
                    $query->where([['i.available_qty', '>', 0], ['i.allow_zero_stock_sale', '=', 0]]);
                })->whereOr(function ($query) {
                    $query->where([['i.allow_zero_stock_sale', '=', 1]]);
                });
            });
        if ($productWhere) {
            $model = $model->where($productWhere);
        }
        if ($param['warehouse_name']) {
            $model = $model->whereRaw('FIND_IN_SET(? , i.wid) > 0', [$param['warehouse_name']]);
        }
        // 采购订单码模糊查询：先获取对应的 inventory_id 集合（仅限非红冲单据）
        if (!empty($param['purchase_no'])) {
            $purchaseNo = trim($param['purchase_no']);
            $inventoryIds = Db::table('db_purchase_receipt_details')
                ->where('purchase_no', '=', $purchaseNo)
                ->where('is_redrush', '=', 0)
                ->distinct(true)
                ->column('inventory_id');
            // 若没有匹配，直接返回空数据
            if (empty($inventoryIds)) {
                $arrData['data'] = ['list' => [], 'total' => 0];
                return $arrData;
            }
            $model = $model->whereIn('i.id', $inventoryIds);
        }
        $total = $model->count();

        // 三个独立排序参数：available_qty, lock_qty, actual_available_qty
        $orderBy = [];
        if (!empty($param['available_qty'])) {
            $orderBy['i.available_qty'] = strtolower($param['available_qty']) === 'asc' ? 'asc' : 'desc';
        }
        if (!empty($param['lock_qty'])) {
            $orderBy['i.lock_qty'] = strtolower($param['lock_qty']) === 'asc' ? 'asc' : 'desc';
        }
        if (!empty($param['actual_available_qty'])) {
            // 直接使用字段名
            $orderBy['actual_available_qty'] = strtolower($param['actual_available_qty']) === 'asc' ? 'asc' : 'desc';
        }
        if (empty($orderBy)) {
            $orderBy = 'i.id desc';
        }

        $result = $model->page($page, $limit)->order($orderBy)->select();


        $warehouseArr = [];
        $opratorArr = [];
        $inventoryArr = [];
        foreach ($result as $value) {
            // 仓库
            $exWarehouse = explode(',', $value['wid']);
            foreach ($exWarehouse as $v) {
                $warehouseArr[] = $v;
            }
            if ($value['creator']) {
                $opratorArr[] = $value['creator'];
            }
            if ($value['updater']) {
                $opratorArr[] = $value['updater'];
            }
            $inventoryArr[] = $value['id'];
        }
        $warehouseArr = array_unique($warehouseArr);
        $opratorArr = array_unique($opratorArr);
        $inventoryArr = array_unique($inventoryArr);

        $warehouseDict = [];
        $warehouseModel = WarehouseModel::whereIn('id', $warehouseArr)->where([['is_del', '=', 0]])->column(['name', 'id']);
        foreach ($warehouseModel as $item) {
            $warehouseDict[$item['id']] = $item['name'];
        }

        $operatorDict = [];
        $oOperator = OperatorModel::whereIn('id', $opratorArr)->column(['cname as name', 'id']);
        foreach ($oOperator as $item) {
            $operatorDict[$item['id']] = $item['name'];
        }

        // 获取价格
        $priceArr = Db::table('db_product_price')
            ->alias('p') // 为 db_product_price 表指定别名 p
            ->field([
                'p.inventory_id',
                'GROUP_CONCAT(c.name) as name',
                'GROUP_CONCAT(p.price) as price',
                'GROUP_CONCAT(p.first_leg_logistics_fee) as first_leg_logistics_fee'
            ]) // 指定需要选择的字段
            ->leftJoin('db_transaction_currency c', 'p.transaction_currency_id = c.id')
            ->where('p.inventory_id', 'in', $inventoryArr)
            ->where('p.is_del', '=', 0)
            ->group('p.inventory_id')
            ->select();
        $priceDict = [];
        foreach ($priceArr as $item) {
            $priceDict[$item['inventory_id']] = [
                'name' => $item['name'],
                'price' => $item['price'],
                'first_leg_logistics_fee' => $item['first_leg_logistics_fee']
            ];
        }

        $result = $result->toArray();

        $redis = (new RedisClient())->getClient();
        $inventory_check_keys_arr  = $redis->keys('inventory_check:*');
        $inventory_check_ids = array_map(fn($key) => str_replace('inventory_check:', '', $key), $inventory_check_keys_arr);

        foreach ($result as &$value) {
            $oInventoryModel = new InventoryModel();
            $value['is_futures_value'] = $oInventoryModel->getIsFuturesValueAttr($value['is_futures'], $value);
            $value['creator_value'] = $operatorDict[$value['creator']] ?? '';
            $value['updater_value'] = $operatorDict[$value['updater']] ?? '';
            $value['transfer_num'] = 0;
            # 是现货 并且可用库存大于锁定库存  可以调拨
            if ($value['is_futures'] == 0 && $value['available_qty'] - $value['lock_qty'] > 0) {
                $value['transfer_num'] = $value['available_qty'] - $value['lock_qty'];
            }

            $widArr = explode(',', $value['wid'] ?? []);
            $warehouseName = [];
            foreach ($widArr as $v) {
                if (isset($warehouseDict[$v])) {
                    $warehouseName[] = $warehouseDict[$v];
                }
            }
            $value['warehouse_name'] = implode(',', $warehouseName);
            $value['warehouse_value'] = implode(',', $warehouseName);
            $value['cost'] = '';
            $value['currency'] = isset($priceDict[$value['id']]) ? $priceDict[$value['id']]['name'] : '';
            $value['price'] = isset($priceDict[$value['id']]) ? $priceDict[$value['id']]['price'] : '';
            $value['first_leg_logistics_fee'] = isset($priceDict[$value['id']]) ? $priceDict[$value['id']]['first_leg_logistics_fee'] : '';
            $value['is_show_check_review_btn'] = in_array($value['id'], $inventory_check_ids) ? 1 : 0; // 是否显示库存校对审核按钮
            $value['check_qty'] = $redis->hGet('inventory_check:' . $value['id'], 'check_qty'); // 库存校对数量
            $value['remark'] = $redis->hGet('inventory_check:' . $value['id'], 'remark'); // 库存校对备注
        }
        $format = ['list' => $result, 'total' => $total];
        $arrData['data'] = $format;
        return $arrData;
    }

    /**
     * 删除库存
     * @param $param
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function delete($param)
    {
        $where = [['is_del', '=', '0'], ['id', 'in', $param['ids']]];
        $oInventoryModel = InventoryModel::where($where);
        $inventory = $oInventoryModel->find();
        if (!$inventory) {
            return ['code' => 1, 'message' => '获取库存信息失败！'];
        }
        $result = $oInventoryModel->update(['is_del' => time()]);
        if ($result) {
            $this->logger->logOperation($param['ids'], 'Inventory', '删除', '删除库存');
            return ['code' => 0, 'message' => '删除库存成功！'];
        } else {
            return ['code' => 1, 'message' => '删除库存失败！'];
        }
    }

    /**
     * 获取库存信息 用于编辑
     * @param $param
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getInfo($param)
    {
        $where = [];
        $where[] = ['id', '=', $param['id']];
        // 获取单条数据 作为 编辑数据
        $oInventoryModel = InventoryModel::with(['product_prices' => function ($query) use ($param) {
            return $query->where('is_del', '=', 0);
        }, 'product', 'get_cname', 'get_warehouse_name', 'get_creator_name', 'get_update_name', 'receipt'])->where($where)->find();
        if (!$oInventoryModel) {
            return ['code' => 1, 'message' => '未找到库存信息！'];
        }
        $currency = isset($param['currency']) ? $param['currency'] : '';
        $warehouse_name = $oInventoryModel->getWarehouseNames();
        $oInventoryModel = $oInventoryModel->toArray();

        $formatData = [];
        $formatData['id'] = $oInventoryModel['id'];
        $formatData['sales_price'] = isset($oInventoryModel['product_price']['price']) ? $oInventoryModel['product_price']['price'] : '';
        $formatData['currency'] = isset($oInventoryModel['product_price']['transaction_currency_id']) ? $oInventoryModel['product_price']['transaction_currency_id'] : $currency;
        $formatData['currency'] = intval($formatData['currency']);
        $formatData['productid'] = $oInventoryModel['productid'];
        $formatData['name'] = $oInventoryModel['cname'];
        $formatData['sku'] = $oInventoryModel['sku'];
        $formatData['warehouse'] = $oInventoryModel['warehouse_name'];
        $formatData['inbound_batch'] = $oInventoryModel['inbound_batch'];
        $formatData['allow_zero_stock_sale'] = $oInventoryModel['allow_zero_stock_sale']; // 期货可转数量
        $enum = InventoryModel::getStaticEnum();
        $is_futures_enum = $enum['is_futures'];
        $formatData['futures'] = $is_futures_enum[$oInventoryModel['is_futures']] ?? '';
        //        $formatData['is_futures'] = $oInventoryModel['is_futures'] == 1 ? '期货' : '现货';
        $formatData['initial_qty'] = $oInventoryModel['initial_qty']; //期初库存数量
        $formatData['convertible_qty'] = $oInventoryModel['convertible_qty']; // 期货可转数量
        $formatData['creator'] = $oInventoryModel['creator_value'];
        $formatData['updater'] = $oInventoryModel['updater_value'];
        $formatData['is_sale'] = $oInventoryModel['is_sale'];
        $formatData['notes'] = $oInventoryModel['remark'];
        $formatData['hashrate'] = $oInventoryModel['product'] ? $oInventoryModel['product']['hashrate'] : '';
        $formatData['cost'] = isset($oInventoryModel['receipt']) ? $oInventoryModel['receipt']['unit_price'] : '';
        $formatData['warehouse_name'] = $warehouse_name;
        $formatData['arrival_date'] = $oInventoryModel['arrival_date'];
        $formatData['real_arrival_date'] = $oInventoryModel['real_arrival_date'];
        $formatData['last_audit_date'] = $oInventoryModel['last_audit_date'];
        $formatData['available_qty'] = $oInventoryModel['available_qty']; //可用库存数量
        $formatData['lock_qty'] = $oInventoryModel['lock_qty']; //锁定库存数量
        $formatData['create_time'] = $oInventoryModel['create_time'];
        $formatData['update_time'] = $oInventoryModel['update_time'];
        $formatData['source_table'] = InventoryModel::getStaticEnum()['source_table'][$oInventoryModel['source_table']] ?? '';
        $formatData['ccname_ids'] =  $oInventoryModel['ccname_ids'] != null ? array_map('intval', explode(',', $oInventoryModel['ccname_ids']))  : [];
        $batchWhere = [
            ['productid', '=', $oInventoryModel['productid']],
            ['arrival_date', '=', $oInventoryModel['arrival_date']],
            ['is_futures', '=', $oInventoryModel['is_futures']],
            ['wid', '=', $oInventoryModel['wid']],
            ['is_del', '=', 0],
            //            ['is_sale','=',1]
        ];
        $batchList = InventoryModel::where($batchWhere)->select()->column('id');

        // 获取采购成本
        $oPurchaseReceiptDetails = PurchaseReceiptDetails::whereIn('inventory_id', $batchList)
            ->field(['supname', 'sales_orderno', 'purchase_no', 'cost', 'order_time'])
            ->distinct(true) // 保证 purchase_no 去重
            ->order('order_time desc')
            ->select();


        if (isset($oInventoryModel['product_prices']) && count($oInventoryModel['product_prices']) > 0) {
            foreach ($oInventoryModel['product_prices'] as $value) {
                $temp = [
                    'currency_id' => $value['transaction_currency_id'],
                    'price' => $value['price'],
                    'wid' => $value['wid'],
                    'first_leg_logistics_fee' => $value['first_leg_logistics_fee']
                ];
                foreach ($value['discount'] as $discount) {
                    $temp['discount'][] = [
                        'level' => $discount['level'],
                        'num' => $discount['num'],
                        'rate' => (float)$discount['rate'],
                        'sales_price' => (float)$discount['price']
                    ];
                }
                $formatData['product_prices'][] = $temp;
            }
        }
        $formatData['product_prices'] = isset($formatData['product_prices']) ? $formatData['product_prices'] : [];
        $formatData['purchase'] = $oPurchaseReceiptDetails;

        // 对齐列表页逻辑：库存校对相关字段
        $redis = (new RedisClient())->getClient();
        $inventory_check_key = 'inventory_check:' . $oInventoryModel['id'];
        $formatData['is_show_check_review_btn'] = $redis->exists($inventory_check_key) ? 1 : 0;
        $formatData['check_qty'] = $redis->hGet($inventory_check_key, 'check_qty');
        $formatData['remark'] = $redis->hGet($inventory_check_key, 'remark');

        return ['code' => 0, 'message' => 'success', 'data' => $formatData];
    }

    public function detail($param)
    {


        $where = [];
        $where[] = ['id', '=', $param['id']];
        $oInventoryModel = InventoryModel::with(
            ['product_prices', 'product', 'get_cname']
        )
            ->where($where)
            ->find();
        $warehouse_name = WarehouseModel::whereIn('id', explode(',', $oInventoryModel->wid))->column('name', 'id');

        if (!$oInventoryModel) {
            return ['code' => 1, 'message' => '未找到库存信息！'];
        }

        $oInventoryModel = $oInventoryModel->toArray();
        $formatData = [];
        $enum = InventoryModel::getStaticEnum();
        $is_futures_enum = $enum['is_futures'];
        //        $formatData['futures'] = $is_futures_enum[$oInventoryModel['is_futures']] ?? '';
        if (isset($oInventoryModel['product_prices'])) {
            foreach ($oInventoryModel['product_prices'] as $key => $value) {
                $temp = [
                    'id' => $key,
                    'name' => $oInventoryModel['cname'],
                    'sku' => $oInventoryModel['sku'],
                    'warehouse' => $warehouse_name[$value['wid']] ?? '',
                    'inbound_batch' => $oInventoryModel['inbound_batch'],
                    'futures' => $is_futures_enum[$oInventoryModel['is_futures']] ?? '',
                    'price' => $value['price'],
                    'currency' => $value['currency'] ? $value['currency']['name'] : '',
                    'level' => '',
                    'wid' => $value['wid'],
                    'num' => '',
                    'rate' => '',
                ];
                $temp['children'] = [];
                if (count($value['discount']) > 0) {
                    foreach ($value['discount'] as $k => $v) {
                        $temp['children'][] = [
                            'id' => $key . '_' . $k,
                            'name' => '',
                            'sku' => '',
                            'warehouse' => '',
                            'inbound_batch' => '',
                            'futures' => '',
                            'currency' => '',
                            'level' => $v['level'],
                            'num' => $v['num'],
                            'rate' => $v['rate'],
                            'price' => $v['price']
                        ];
                    }
                }
                $formatData[] = $temp;
            }
        }
        return ['code' => 0, 'message' => 'success', 'data' => $formatData];
    }

    /**
     * 修改/添加 商品折扣数据
     * @param $param
     * @return void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * 2025-01-03 16 47 55
     * author: jiang
     */
    public function fixSavePrice($param)
    {
        // 清空价格数据
        $where = [['is_del', '=', '0'], ['id', '=', $param['id']]];
        $oInventoryModel = InventoryModel::where($where)->find();

        $oInventoryModel->is_sale = $param['is_sale'];
        $oInventoryModel->remark = $param['remark'];

        $oInventoryModel->ccname_ids = implode(',', $param['ccname_ids']);

        if ($param['real_arrival_date'] && $oInventoryModel->real_arrival_date != $param['real_arrival_date']) {
            $oInventoryModel->real_arrival_date = $param['real_arrival_date'];
        }

        $batchWhere = [
            ['productid', '=', $oInventoryModel->productid],
            ['wid', '=', $oInventoryModel->wid],
            ['arrival_date', '=', $oInventoryModel->arrival_date],
            ['is_futures', '=', $oInventoryModel->is_futures]
        ];
        $batchIds = InventoryModel::where($batchWhere)->column('id');

        /* 批量修改是否支持零库存 */
        if (!is_null($param['allow_zero_stock_sale']) && $oInventoryModel->allow_zero_stock_sale != $param['allow_zero_stock_sale']) {

            InventoryModel::where('id', 'in', $batchIds)->update([
                'allow_zero_stock_sale' => $param['allow_zero_stock_sale'],
                'update_time' => date('Y-m-d H:i:s', time()),
                'updater' => $param['operator_id'],
            ]);
        }

        /* 保存 */
        if (!$oInventoryModel->save()) {
            return ['code' => 1, 'message' => '保存失败'];
        }

        $productPrice = new ProductPrice(); // 取消价格变更影响到的订单
        ProductPriceModel::where([['inventory_id', 'in', $batchIds]])->delete(); // 独立于事务外 后需要修正

        foreach ($param['product_prices'] as $value) {
            $arguments = [
                'id' => $param['id'],
                'is_sale' => $param['is_sale'],
                'wid' => $value['wid'],
                'operator_id' => $param['operator_id'],
                'currency' => $value['currency_id'],
                'sales_price' => $value['price'],
                'discount' => $value['discount'],
                'first_leg_logistics_fee' => $value['first_leg_logistics_fee']
            ];

            $result = $this->savePrice($arguments);

            foreach ($value['discount'] as &$discountValue) { // 修改商品报价影响到的订单价格
                $discountValue['price'] = $discountValue['sales_price'];
            }
            $productPrice->cannelPriceChangeAffectedRelatedOrders($oInventoryModel->productid,  [$oInventoryModel->wid], $oInventoryModel->real_arrival_date, $oInventoryModel->is_futures, $value['currency_id'], $value['price'], $value['first_leg_logistics_fee'], $value['discount']);
        }


        $this->clearCTerminalCache(6); // 清除C端产品缓存
        return ['code' => 0, 'message' => 'success'];
    }


    /**
     * @describe 库存校对/审核库存校对
     * @author: Bobo
     * @date: 2025-07-23 11:47:58
     * @param [type] @required
     * @return Renderable
     */
    public function submitCheckApi($param)
    {
        try {
            $redis = (new RedisClient())->getClient();
            $notificationService = new CompleteNotificationService();
            $inventory = InventoryModel::where('id', $param['id'])->with(['get_cname'])->find();

            if (!$inventory) {
                return ['code' => 1, 'message' => '库存不存在'];
            }

            if ($param['action_type'] == '1') {
                return $this->submitCheck($param, $inventory, $redis, $notificationService);
            } elseif ($param['action_type'] == '2') {
                return $this->approveCheck($param, $inventory, $redis, $notificationService);
            } elseif ($param['action_type'] == '3') {
                return $this->rejectCheck($param, $inventory, $redis, $notificationService);
            } elseif ($param['action_type'] == '4') {
                return $this->cancelCheck($param, $inventory, $redis, $notificationService);
            } else {
                return ['code' => 1, 'message' => '无效的操作类型'];
            }
        } catch (\Throwable $e) {
            Log::error('submitCheckApi error: ' . $e->getMessage());
            return [
                'code' => 500001,
                'message' => '操作失败：' . $e->getMessage(),
            ];
        }
    }

    /**
     * @describe 校对库存
     * @author: Bobo
     * @date: 2025-07-23 11:51:57
     * @param [type] @required
     * @return Renderable
     */
    private function submitCheck($param, $inventory, $redis, $notificationService)
    {
        $is_exist = $redis->hGet('inventory_check:' . $param['id'], 'id');
        if ($is_exist) {
            return ['code' => 1, 'message' => '该库存已存在一条库存校对数据，请勿重复提交'];
        }

        $redis->hMSet('inventory_check:' . $param['id'], [
            'id' => $param['id'],
            'available_qty' => $param['available_qty'],
            'check_qty' => $param['check_qty'],
            'lock_qty' => $param['lock_qty'],
            'remark' => $param['remark'],
            'updater' => $param['operator_id'],
            'update_time' => date('Y-m-d H:i:s', time())
        ]);

        $content = $this->buildNotificationContent($param, $inventory, 'check');

        $env = env('APP_ENV') ?? 'prod';
        $domain = Config::get('domain')[$env]['erphome'];
        $url = $domain . '#/warehouse/inventory-management/checking?id=' . $inventory->id;
        $notificationService->send('inventory_check', $param, [], $content, $url);
        $this->logger->logOperation($inventory->id, 'inventory', '库存-校对发起', '库存-校对发起',1,'inventory',$inventory->id,'1,10');

        return ['code' => 0, 'message' => 'success'];
    }

    /**
     * @describe 审核库存校对
     * @author: Bobo
     * @date: 2025-07-23 11:51:57
     * @param [type] @required
     * @return Renderable
     */
    private function approveCheck($param, $inventory, $redis, $notificationService)
    {
        $newavailable_qty = $inventory->available_qty + $param['check_qty'];
        $newinitial_qty = $inventory->initial_qty + $param['check_qty'];
        $new_convertible_qty = $inventory->convertible_qty + $param['check_qty'];

        $oInventoryModel = InventoryModel::where(['id' => $param['id']])
            ->inc('initial_qty', $param['check_qty'])
            ->inc('available_qty', $param['check_qty']);
        if ($inventory->is_futures !== 0) {
            $oInventoryModel = $oInventoryModel->inc('convertible_qty', $param['check_qty']);
        }
        $oInventoryModel->update([
            'updater' => $param['operator_id'],
            'update_time' => date('Y-m-d H:i:s', time())
        ]);

        $recipients = $redis->hGet('inventory_check:' . $param['id'], 'updater');
        $redis->del('inventory_check:' . $param['id']);

        $value = [
            'num' => $param['check_qty'],
            'inventory_id' => $param['id']
        ];


        $content = $this->buildNotificationContent($param, $inventory, 'approve');
        $notificationService->send('inventory_check', $param, [$recipients], $content);

        $param['remark'] .= " (old_available_qty : {$inventory->available_qty} , new_available_qty : {$newavailable_qty})";
        $param['remark'] .= " (old_initial_qty : {$inventory->initial_qty} , new_initial_qty : {$newinitial_qty})";
        $param['remark'] .= " (old_convertible_qty : {$inventory->convertible_qty} , new_convertible_qty : {$new_convertible_qty})";
        $this->insertInventoryChanggeData($param, $value, '库存校对', $param['remark']);
        $this->clearCTerminalCache(6);
        $approverWhere = [
            'child_entity_id' => $inventory->id,
            'business_module' => 'inventory',
            'child_business_module' => 'inventory',
            'operate' => '库存-校对发起',

        ];
        $this->logger->updateApprover($approverWhere, $param['operator_id']);
        $this->logger->logOperation($inventory->id, 'inventory', '库存-校对审核通过', '库存-校对审核通过');
        return ['code' => 0, 'message' => 'success'];
    }

    /**
     * @describe 驳回库存校对
     * @author: jiang
     * @date: 2025-08-22 11:51:57
     * @param [type] @required
     * @return Renderable
     */
    private function rejectCheck($param, $inventory, $redis, $notificationService)
    {
        // 获取提交校对的人员ID
        $recipients = $redis->hGet('inventory_check:' . $param['id'], 'updater');

        // 删除Redis中的校对数据
        $redis->del('inventory_check:' . $param['id']);

        // 构建拒绝通知内容
        $content = $this->buildNotificationContent($param, $inventory, 'reject');

        // 发送拒绝通知
        $notificationService->send('inventory_check', $param, [$recipients], $content);
        $approverWhere = [
            'child_entity_id' => $inventory->id,
            'business_module' => 'inventory',
            'child_business_module' => 'inventory',
            'operate' => '库存-校对发起',

        ];
        $this->logger->updateApprover($approverWhere, $param['operator_id']);
        $this->logger->logOperation($inventory->id, 'inventory', '库存-校对审核驳回', '库存-校对审核驳回');
        return ['code' => 0, 'message' => '拒绝成功'];
    }
    private function cancelCheck($param, $inventory, $redis, $notificationService)
    {
        // 删除Redis中的校对数据
        $redis->del('inventory_check:' . $param['id']);
        $this->logger->logOperation($inventory->id, 'inventory', '库存-校对撤销', '库存-校对撤销');
        return ['code' => 0, 'message' => '拒绝成功'];
    }

    /**
     * @describe 构建库存校对通知内容
     * @author: Bobo
     * @date: 2025-07-23 11:51:57
     * @param [type] @required
     * @return Renderable
     */
    private function buildNotificationContent($param, $inventory, $type = 'check')
    {
        $content = '';
        if ($type == 'check') {
            $content = "您有一条新的库存校对数据需要审核，请及时处理\n\n";
        } elseif ($type == 'approve') {
            $content = "您有一条库存校对数据已审核，请及时核对库存数量\n\n";
        } elseif ($type == 'reject') {
            $content = "您有一条库存校对数据被驳回，请及时处理\n\n";
        }

        $content .= "库存ID：" . $param['id'] . "\n\n";
        $content .= "商品名称：" . $inventory->cname . "\n\n";
        $content .= "商品编码：" . $inventory->sku . "\n\n";

        if (0 == $inventory->is_futures) {
            $content .= "物流批次：" . $inventory->inbound_batch . "\n\n";
        } else {
            $content .= "库存类型：" . (1 == $inventory->is_futures ? "在途期货" : "大期货") . "\n\n";
            $content .= "到货日期：" . $inventory->arrival_date . "\n\n";
        }

        $content .= "库存数量：" . $param['available_qty'] . "\n\n";
        $content .= "校对数量：" . ($param['check_qty'] > 0 ? '+' . $param['check_qty'] : $param['check_qty']) . "\n\n";
        $content .= "备注：" . $param['remark'] . "\n\n";

        return $content;
    }

    /**
     * 校对库存
     * @param $param
     * @return void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * 2025-01-03 16 47 55
     * author: jiang
     */
    public function submitCheckApiold1($param)
    {
        try {
            $redis = (new RedisClient())->getClient();
            $notificationService = new CompleteNotificationService();
            $inventory = InventoryModel::where('id', $param['id'])->with(['get_cname'])->find();

            if ($param['action_type'] == '1') { // 校对
                if ($param['check_qty'] == $param['available_qty']) {
                    return ['code' => 1, 'message' => '数据没有更新'];
                }

                $is_exist = $redis->hGet('inventory_check:' . $param['id'], 'id');
                if ($is_exist) {
                    return ['code' => 1, 'message' => '该库存已存在一条库存校对数据，请勿重复提交'];
                }

                $redis->hMSet('inventory_check:' . $param['id'], [
                    'id' => $param['id'],
                    'available_qty' => $param['available_qty'],
                    'check_qty' => $param['check_qty'],
                    'lock_qty' => $param['lock_qty'],
                    'remark' => $param['remark'],
                    'updater' => $param['operator_id'],
                    'update_time' => date('Y-m-d H:i:s', time())
                ]);



                $content = "有一条新的库存校对数据需要您审核，请及时处理\n\n";
                $content .= "库存ID：" . $param['id'] . "\n\n";
                $content .= "商品名称：" . $inventory->cname . "\n\n";
                $content .= "商品编码：" . $inventory->sku . "\n\n";
                if (0 == $inventory->is_futures) {
                    $content .= "物流批次：" . $inventory->inbound_batch . "\n\n";
                } else {
                    $content .= "库存类型：" . (1 == $inventory->is_futures ? "在途期货" : "大期货") . "\n\n";
                    $content .= "到货日期：" . $inventory->arrival_date . "\n\n";
                }
                $content .= "库存数量：" . $param['available_qty'] . "\n\n";
                $content .= "校对数量：" . $param['check_qty'] . "\n\n";
                $content .= "备注：" . $param['remark'] . "\n\n";


                $notificationService->send('inventory_check', $param, [], $content);
            } else { // 审核校对数据
                InventoryModel::where([
                    'id' => $param['id']
                ])->update([
                    'available_qty' => $param['available_qty'] + $param['check_qty'],
                    'updater' => $param['operator_id'],
                    'update_time' => date('Y-m-d H:i:s', time())
                ]);
                $recipients = $redis->hGet('inventory_check:' . $param['id'], 'updater');
                $redis->del('inventory_check:' . $param['id']);
                $value = [
                    'num' => $param['check_qty'],
                    'inventory_id' => $param['id']
                ];
                $param['remark'] .= " (old_available_qty : {$param['available_qty']} , new_available_qty : " . ($param['available_qty'] + $param['check_qty']) . ")";
                $this->insertInventoryChanggeData($param, $value, '库存校对', $param['remark']);
                $this->clearCTerminalCache(6); // 清除C端产品缓存

                $content = "有一条库存校对数据已审核，请及时核对库存数量\n\n";
                $content .= "库存ID：" . $param['id'] . "\n\n";
                $content .= "商品名称：" . $inventory->cname . "\n\n";
                $content .= "商品编码：" . $inventory->sku . "\n\n";
                if (0 == $inventory->is_futures) {
                    $content .= "物流批次：" . $inventory->inbound_batch . "\n\n";
                } else {
                    $content .= "库存类型：" . (1 == $inventory->is_futures ? "在途期货" : "大期货") . "\n\n";
                    $content .= "到货日期：" . $inventory->arrival_date . "\n\n";
                }
                $content .= "库存数量：" . $param['available_qty'] . "\n\n";
                $content .= "校对数量：" . $param['check_qty'] . "\n\n";
                $content .= "备注：" . $param['remark'] . "\n\n";

                $notificationService->send('inventory_check', $param, [$recipients], $content);
            }


            return ['code' => 0, 'message' => 'success'];
        } catch (\Throwable $e) {
            // 记录日志
            Log::error('submitCheckApi error: ' . $e->getMessage());
            return [
                'code' => 500001,
                'message' => '操作失败：' . $e->getMessage(),
            ];
        }
    }

    public function submitCheckApiold($param)
    {
        // 清空价格数据
        $where = [['is_del', '=', '0'], ['id', '=', $param['id']]];

        $num = $param['available_qty'];
        $update = ['available_qty' => $param['check_qty']];
        if ($param['check_qty'] == $num) {
            return ['code' => 1, 'message' => '数据没有更新'];
        }
        /* 保存 */
        if (!InventoryModel::where('lock_qty', '<=', $param['check_qty'])->where($where)->where(['available_qty' => $num, 'lock_qty' => $param['lock_qty']])->update($update)) {
            return ['code' => 1, 'message' => '保存失败'];
        }
        $param['remark'] .= " (old_available_qty : {$num} , new_available_qty : {$param['check_qty']})";
        $value = [];
        $value['num'] = $num;
        $value['inventory_id'] = $param['id'];
        $this->insertInventoryChanggeData($param, $value, '库存校对', $param['remark']);
        $this->clearCTerminalCache(6); // 清除C端产品缓存
        return ['code' => 0, 'message' => 'success'];
    }

    /**
     * 修改/添加 商品折扣数据
     * @param $param
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function savePrice($param)
    {
        Db::startTrans();
        try {
            //查询币种信息
            $currency = TransactionCurrencyModel::where('id', $param['currency'])->find();
            if (!$currency) {
                throw new Exception("未找到币种数据！");
            }

            $where = [['is_del', '=', '0'], ['id', '=', $param['id']]];
            $oInventoryModel = InventoryModel::where($where)->find();
            if (!$oInventoryModel) {
                throw new Exception("未找到库存数据！");
            }
            if (isset($param['is_sale'])) {
                $oInventoryModel->is_sale = $param['is_sale'];
            }
            $oInventoryModel->updater = $param['operator_id'];
            $oInventoryModel->update_time = date('Y-m-d H:i:s');
            if (!$oInventoryModel->save()) {
                throw new Exception("库存数据保存失败！");
            }
            $batchWhere = [['is_del', '=', 0], ['productid', '=', $oInventoryModel->productid],  ['arrival_date', '=', $oInventoryModel->arrival_date], ['is_futures', '=', $oInventoryModel->is_futures]];
            $batchIds = InventoryModel::where($batchWhere)->whereFindInSet('wid', $param['wid'])->column('id');

            foreach ($batchIds as $id) {
                $oProductPriceModel = ProductPriceModel::where([['is_del', '=', 0], ['wid', '=', $param['wid']], ['inventory_id', '=', $id], ['transaction_currency_id', '=', $param['currency']]])->find();

                if ($oProductPriceModel) {
                    $oProductPriceModel->update_time = date('Y-m-d H:i:s', time());
                    $oProductPriceModel->updator = $param['operator_id'];
                } else {
                    $oProductPriceModel = new ProductPriceModel();
                    $oProductPriceModel->creator = $param['operator_id'];
                    $oProductPriceModel->create_time = date('Y-m-d H:i:s', time());
                }

                // 更新商品价格
                $oProductPriceModel->inventory_id = $id;
                $oProductPriceModel->wid = $param['wid'];
                $oProductPriceModel->transaction_currency_id = $param['currency'];
                $oProductPriceModel->price = $param['sales_price'];
                if (isset($param['first_leg_logistics_fee']) && $param['first_leg_logistics_fee'] != '') {
                    $oProductPriceModel->first_leg_logistics_fee = $param['first_leg_logistics_fee'];
                }



                if (!$oProductPriceModel->save()) {
                    throw new Exception("价格数据保存失败！");
                }

                // 清空折扣信息
                $delWhere = [
                    ['price_id', '=', $oProductPriceModel->id]
                ];
                ProductDiscountModel::where($delWhere)->delete();

                $data = [];
                foreach ($param['discount'] as $key => $value) {
                    $price = $param['sales_price']; // 报价
                    $sale_price = $value['sales_price']; //折扣价
                    if ($price != 0) {
                        $rate = ($sale_price / $price) * 100;
                    } else {
                        // 防止除以零的情况
                        $rate = 0;
                    }
                    $data[] = [
                        'level' => $value['level'],
                        'price' => $value['sales_price'],
                        'num' => $value['num'],
                        //                        'rate' => $value['rate'],
                        'rate' => $rate, // 修改成后端计算折扣率
                        'price_id' => $oProductPriceModel->id,
                        'creator' => $param['operator_id'],
                        'create_time' => date('Y-m-d H:i:s', time())
                    ];
                }
                $result = ProductDiscountModel::insertAll($data);
                if (!$result) {
                    throw new Exception("添加折扣数据失败！");
                }
            }
            DB::commit();
        } catch (Exception $e) {
            Db::rollback();
            return ['code' => 1, 'message' => $e->getMessage()];
        }
        // todo 获取不到id
        $this->logger->logOperation([], 'Inventory', '保存', '保存折扣');
        return ['code' => 0, 'message' => '保存折扣成功！'];
    }

    /**
     * 获取库存转换数据
     * @param $param
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function transDetail($param)
    {
        // 查询库存信息
        $where = [['is_del', '=', '0'], ['id', '=', $param['id']]];
        // 获取库存基本信息
        $oInventoryModel = InventoryModel::with(['get_cname', 'get_creator_name', 'get_update_name'])->append(['is_futures_value', 'warehouse_value'])->where($where)->find();
        if (!$oInventoryModel) {
            return ['code' => 1, 'message' => '未找到库存信息！'];
        }

        $warehouse_list = [];
        $wids = explode(',', $oInventoryModel->wid);

        $fl_wids = WarehouseModel::whereIn('fl_warehouse_id', explode(',', $oInventoryModel->wid))->column('id');
        $oInventoryModel->has_first_warehouse = 0;
        if (count($fl_wids) > 0) {
            $wids = $fl_wids;
            $oInventoryModel->has_first_warehouse = 1;
        }

        if ($oInventoryModel->wid) {
            $warehouse_list = WarehouseModel::whereIn('id', $wids)
                ->where([
                    'is_del' => 0,
                    'status' => 1
                ])->column(['name as label', 'id as value']);
        }
        $oInventoryModel->warehouse_list = $warehouse_list;

        // 格式化数据
        $oInventoryModel->is_sale = InventoryModel::getStaticEnum()['is_sale'][$oInventoryModel->is_sale] ?? '';




        return ['code' => 0, 'message' => 'success', 'data' => $oInventoryModel->toArray()];
    }

    /**
     * 获取库存订单列表
     * @param $param
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * 2024-11-27 15 46 27
     * author: jiang
     */
    public function getOrderByInventory($param)
    {
        $inventoryTransSave = new InventoryTransSave();
        return $inventoryTransSave->getOrderByInventory($param);
    }

    /**
     * 获取可转换库存状态
     * @param $param
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function transEnum($param)
    {
        $where = [['is_del', '=', '0'], ['id', '=', $param['id']]];
        $oInventoryModel = InventoryModel::where($where)->find();
        if (!$oInventoryModel) {
            return ['code' => 1, 'message' => '未找到库存信息！'];
        }
        $futures = InventoryModel::getStaticEnum()['is_futures'];
        $data = [];
        foreach ($futures as $key => $value) {
            if ($oInventoryModel->is_futures > $key) {
                $data[] = [
                    'label' => $value,
                    'value' => $key,
                ];
            }
        }
        if (count($data) == 1) {
            $data[0]['selected'] = true;
        }

        return ['code' => 0, 'message' => 'success', 'data' => $data];
    }

    /**
     * 转换库存
     * @param $param
     *
     * @return array
     */
    public function transSave($param)
    {

        $inventoryTransSave = new InventoryTransSave();
        $res = $inventoryTransSave->transSave($param);
        if ($res['code'] == 1) {
            return $res;
        }

        $this->logger->logOperation($param['id'], 'Inventory', '转换', '库存转换');
        return $res;
    }
    /**
     * @describe 设置库存销售状态
     */
    public function sale($param)
    {
        if ($param['is_sale'] == 1) {
            $oProductPriceModel = ProductPriceModel::with(['discount'])->where('inventory_id', 'in', $param['ids'])->where('is_del', 0)->find();
            if (!$oProductPriceModel || count($oProductPriceModel->discount) == 0) {
                return ['code' => 1, 'message' => '该库存没有价格，不可以销售！'];
            }
        }
        InventoryModel::where('id', 'in', $param['ids'])->update([
            'is_sale' => $param['is_sale']
        ]);
        $this->clearCTerminalCache(6); // 清除C端产品缓存
        $this->logger->logOperation($param['ids'], 'Inventory', '设置', '设置库存销售状态');
        return ['code' => 0, 'message' => '设置成功！'];
    }

    /**
     * @describe 设置零库存销售状态
     */
    public function allowZero($param)
    {

        $oInventoryModel = InventoryModel::where('id', 'in', $param['ids'])->where('is_del', 0)->find();
        if (!$oInventoryModel) {
            return ['code' => 1, 'message' => '库存不存在'];
        }

        InventoryModel::where('id', 'in', $param['ids'])->update([
            'allow_zero_stock_sale' => $param['allow_zero_stock_sale']
        ]);
        $this->clearCTerminalCache(6); // 清除C端产品缓存
        $this->logger->logOperation($param['ids'], 'Inventory', '设置', '设置零库存销售状态');
        return ['code' => 0, 'message' => '设置成功！'];
    }

    public function getFieldEnum($field)
    {
        $model = new InventoryModel();
        $res = $model->getFieldEnum($field);
        return [
            'code' => 0,
            'data' => $res
        ];
    }
    public function mergeCreateOrder($param, $page = 1, $limit = 10)
    {
        // 基础查询条件
        $where = [['i.is_del', '=', 0]];
        if ($param['type'] == 1) {
            $where[] = ['i.is_sale', '=', 1];
        }
        $currency = $param['currency'] ?? 214; // 默认货币ID
        if (isset($param['product']) && $param['product']) {
            $where[] = ['p.cname', 'like', '%' . $param['product'] . '%'];
        }
        if ($param['wid']) {
            // $where[] = ['i.wid', '=', $param['wid']];
            // $where[] = ['i.wid', 'FIND_IN_SET', $param['wid']];
        }
        if ($param['brand']) {
            $where[] = ['p.brand', '=', $param['brand']];
        }
        if ($param['is_futures'] != null) {
            $where[] = ['i.is_futures', '=', $param['is_futures']];
        }
        if ($param['start_date']) {
            $where[] = ['i.arrival_date', '>=', $param['start_date']];
        }
        if ($param['end_date']) {
            $where[] = ['i.arrival_date', '<', $param['end_date']];
        }

        // 第一次查询：获取库存数据
        $model = Db::table('db_inventory')
            ->alias('i')
            ->field([
                'i.productid as product_id',
                'i.arrival_date',
                'GROUP_CONCAT(DISTINCT i.real_arrival_date) as real_arrival_date',
                'i.is_futures',
                'i.wid',
                'i.allow_zero_stock_sale',
                'i.is_sale',
                'p.cname as product_name',
                'p.code as product_code',
                'p.expiration_date',
                'p.brand',
                'p.hashrate',
                'p.billing_weight',
                'p.free_shipping',
                'p.apply_rules',
                'SUM(i.available_qty - i.lock_qty) as quantity',
                'GROUP_CONCAT(i.id) as inventory_ids' // 库存ID集合
            ])
            ->leftJoin('db_product p', 'i.productid = p.id')
            ->group('i.productid, i.wid, i.arrival_date, i.is_futures, i.allow_zero_stock_sale,i.is_sale')
            ->whereRaw(' i.allow_zero_stock_sale = 1 or (i.available_qty > i.lock_qty)')
            ->where(function ($query) use ($param) {
                if ($param['wid']) {
                    $query->whereRaw("FIND_IN_SET(?, i.wid) > 0", [$param['wid']]);
                }
            })
            ->where($where);




        $total = $model->count(); // 获取总数
        $result = $model->select(); // 获取查询结果
        $data = $result->toArray(); // 转换为数组

        // 格式化数据
        $format = [];
        foreach ($data as $datum) {
            $wid_arr = explode(',', $datum['wid']);
            if (count($wid_arr) == 1) {
                $key = $datum['product_id'] . '_' . $datum['arrival_date'] . '_' . $datum['is_futures'] . '_' . $datum['wid'];
                if (isset($format[$key])) {
                    $format[$key]['quantity'] += $datum['quantity'];
                } else {
                    $fake = $datum;
                    $fake['wid'] = reset($wid_arr);
                    $format[$key] = $fake;
                }
            } else {
                foreach ($wid_arr as $wid) {
                    $key = $datum['product_id'] . '_' . $datum['arrival_date'] . '_' . $datum['is_futures'] . '_' . $wid;
                    if (isset($format[$key])) {
                        $format[$key]['quantity'] += $datum['quantity'];
                    } else {
                        $fake = $datum;
                        $fake['wid'] = $wid;
                        $fake['share_id'] = $datum['inventory_ids'];
                        $format[$key] = $fake;
                    }
                }
            }
            unset($datum['inventory_ids']);
        }
        // 获取币种信息
        $currencyIds = [$currency, 214]; // 客户选定的币种和美金
        $currencyData = Db::table('db_transaction_currency')
            ->whereIn('id', $currencyIds)
            ->field('abbr,name,id')
            ->select()
            ->toArray();
        $currencyData = array_column($currencyData, null, 'id');

        $customerPaymentCurrencyData = $currencyData[$currency] ?? null;
        $usdCurrencyData = $currencyData[214] ?? null;


        // 获取所有库存ID的价格数据
        $allInventoryIds = [];
        $allInventoryWidIds = [];
        foreach ($format as $item) {
            $inventoryid = explode(',', $item['inventory_ids'])[0];
            $inventorywid = $inventoryid . '_' . $item['wid'];
            array_push($allInventoryIds,  $inventoryid); //  productid, wid, arrival_date, is_futures 分组后每组的价格是相同的，所以只取第一个
            array_push($allInventoryWidIds,  $inventorywid); //  拼接 仓库id
        }
        $allInventoryIds = array_unique($allInventoryIds);
        $allInventoryWidIds = array_unique($allInventoryWidIds);

        // 批量查询所有价格信息
        $pricesData = ProductPriceModel::with(
            [
                'discount' => function ($query) {
                    $query->field('id, num, price , price_id , level'); // 指定关联表字段，必须包含外键 price_id
                }
            ]
        )
            ->whereIn('inventory_id', $allInventoryIds)
            ->where('transaction_currency_id', $currency)
            ->field('id,
            inventory_id,
            wid,
            transaction_currency_id, price , first_leg_logistics_fee, "' .
                $customerPaymentCurrencyData['name'] . '" as actual_quoted_currency_name, "' .
                $customerPaymentCurrencyData['name'] . '" as customer_payment_currency_name') // 明确指定主表字段（避免字段与条件冲突）
            ->select()
            ->toArray();
        // 将 inventory_id 作为结果数组的键
        $currencyPricesDataInventoryId = [];
        foreach ($pricesData as $pricesDatum) {
            $currencyPricesDataInventoryId[] = $pricesDatum['inventory_id'] . '_' . $pricesDatum['wid'];
        }
        $currencyPricesDataInventoryId = array_unique($currencyPricesDataInventoryId); // 查询到默认价格的库存ID


        if ($currency != 214) {  // 如果需要查询美金价格（当前币种不是美金时）
            $dollarPricesDataInventoryId = array_diff($allInventoryWidIds, $currencyPricesDataInventoryId);
            $diff = [];
            $diffwid = [];
            foreach ($dollarPricesDataInventoryId as $valuePrice) {
                $diff[] = explode('_', $valuePrice)[0];
                $diffwid[] = explode('_', $valuePrice)[1];
            }

            $dollerPricesData =  ProductPriceModel::with(
                [
                    'discount' => function ($query) {
                        $query->field('id, num, price , price_id , level'); // 指定关联表字段，必须包含外键 price_id
                    }
                ]
            )
                ->whereIn('inventory_id', $diff)
                ->whereIn('wid', $diffwid)
                ->where('transaction_currency_id', 214)
                ->field('id,
                inventory_id,
                 wid,
                transaction_currency_id, price , first_leg_logistics_fee, "' .
                    $usdCurrencyData['name'] . '" as actual_quoted_currency_name, "' .
                    $customerPaymentCurrencyData['name'] . '" as customer_payment_currency_name') // 明确指定主表字段（避免字段与条件冲突）
                ->select()
                ->toArray(); // 获取美金价格
            $pricesData = array_merge($pricesData, $dollerPricesData);
        }
        $pricesDatabase = [];
        foreach ($pricesData as $pricesDatum) {
            $key = $pricesDatum['inventory_id'] . '_' . $pricesDatum['wid'];
            $pricesDatabase[$key] = $pricesDatum;
        }


        // 获取汇率 API 实例
        $fetcher = new ExchangeRateHostAPI();
        $exchange_rate = $fetcher->getRate($usdCurrencyData['abbr'], $customerPaymentCurrencyData['abbr']);

        if (!is_numeric($exchange_rate)) {
            return ['code' => 1, 'message' => '汇率获取失败' . $exchange_rate];
        }

        // 循环处理库存数据，匹配价格信息
        foreach ($format as $key => &$value) {
            // 获取当前库存组的第一个 inventory_id
            $inventory_id = explode(',', $value['inventory_ids'])[0];
            $priceKey = $inventory_id . '_' . $value['wid'];
            $value['wid'] = intval($value['wid']);
            // 检查是否有对应的价格数据
            if (!isset($pricesDatabase[$priceKey])) {
                if ($param['type'] == 1) {  // 如果type=1 没有价格数据，过滤掉  1是下单
                    unset($format[$key]);
                }
                continue;
            }

            // 获取价格数据
            $priceInfo = $pricesDatabase[$priceKey];

            $price_ids = [$priceInfo['id']]; // 价格ID集合
            $price_values = [$priceInfo['price']]; // 价格集合

            // 设置价格相关字段
            $value['prices'] = implode(',', $price_values); // 价格字符串
            $value['price_ids'] = implode(',', $price_ids); // 价格ID字符串
            $value['first_leg_logistics_fee'] = $priceInfo['first_leg_logistics_fee']; // 头程物流费
            $value['original_price'] = reset($price_values); // 原价
            $value['actual_price'] = reset($price_values); // 实际价格
            $value['original_actual_price'] = reset($price_values); // 原始实际价格
            $value['actual_quoted_currency_name'] =  $priceInfo['actual_quoted_currency_name']; // 实际价格币种名称
            $value['customer_payment_currency_name'] =  $priceInfo['customer_payment_currency_name']; // 客户支付币种名称
            $value['actual_quoted_currency'] = $priceInfo['transaction_currency_id'];
            $value['brand'] = intval($value['brand']);
            // $value['wid'] = intval($value['wid']);
            // 处理折扣信息
            $value['discount_price'] = [];
            if (!empty($priceInfo['discount'])) {
                $discount = $priceInfo['discount'];
                foreach ($discount as &$discount_price) {
                    if ($discount_price['level'] == 1) {
                        $value['actual_price'] = $discount_price['price']; // 更新实际价格
                    }
                    if ($priceInfo['transaction_currency_id'] != $currency) {
                        // 客户选定的币种 != 库存报价币种，计算实际售卖折扣价格
                        $discount_price['discount_actual_selling_price'] = round($discount_price['price'] * $exchange_rate, 2);
                    } else {
                        $discount_price['discount_actual_selling_price'] = $discount_price['price'];
                    }
                }
                $value['discount_price'] = $discount; // 折扣信息
            }

            // 计算实际售卖价格
            if ($priceInfo['transaction_currency_id'] == $currency) {
                // 客户选定的币种 == 库存报价币种
                $value['original_actual_selling_price'] = $value['original_price']; // 原始客户付款币种价格
                $value['actual_selling_price'] = $value['actual_price']; // 实际客户付款币种价格
            } else {
                // 客户选定的币种 != 库存报价币种，需要汇率转换

                $value['original_actual_selling_price'] = round($value['original_price'] * $exchange_rate, 2); // 原始客户付款币种价格
                $value['actual_selling_price'] = round($value['actual_price'] * $exchange_rate, 2); // 实际客户付款币种价格
            }

            // 设置唯一标识
            $value['unique'] = $value['product_id'] . '_' . $value['arrival_date'] . '_' . $value['is_futures'] . '_' . $value['wid'];
        }

        // 处理仓库信息
        $warehouse_arr = array_unique(array_column($format, 'wid'));
        $fl_data = WarehouseModel::whereIn('id', $warehouse_arr)->column('fl_warehouse_id', 'id');
        foreach ($format as &$item) {
            $item['fl_warehouse_id'] = $fl_data[$item['wid']] ?? $item['wid'];
        }
        // 返回结果
        $format = ['list' => array_values($format), 'total' => $total];
        return ['code' => 0, 'message' => 'success', 'data' => $format];
    }

    // public function mergeCreateOrderBak($param, $page = 1, $limit = 10)
    // {
    //     // 基础查询条件
    //     $where = [['i.is_del', '=', 0]];
    //     if ($param['type'] == 1) {
    //         $where[] = ['i.is_sale', '=', 1];
    //     }
    //     $currency = $param['currency'] ?? 214; // 默认货币ID
    //     if (isset($param['product']) && $param['product']) {
    //         $where[] = ['p.cname', 'like', '%' . $param['product'] . '%'];
    //     }
    //     if ($param['wid']) {
    //         $where[] = ['i.wid', '=', $param['wid']];
    //     }
    //     if ($param['brand']) {
    //         $where[] = ['p.brand', '=', $param['brand']];
    //     }
    //     if ($param['is_futures'] != null) {
    //         $where[] = ['i.is_futures', '=', $param['is_futures']];
    //     }
    //     if ($param['start_date']) {
    //         $where[] = ['i.arrival_date', '>=', $param['start_date']];
    //     }
    //     if ($param['end_date']) {
    //         $where[] = ['i.arrival_date', '<', $param['end_date']];
    //     }

    //     // 第一次查询：获取库存数据
    //     $model = Db::table('db_inventory')
    //         ->alias('i')
    //         ->field([
    //             'i.productid as product_id',
    //             'i.arrival_date',
    //             'i.is_futures',
    //             'i.wid',
    //             'p.cname as product_name',
    //             'p.code as product_code',
    //             'p.expiration_date',
    //             'p.brand',
    //             'p.hashrate',
    //             'SUM(i.available_qty - i.lock_qty) as quantity',
    //             'GROUP_CONCAT(i.id) as inventory_ids' // 库存ID集合
    //         ])
    //         ->leftJoin('db_product p', 'i.productid = p.id')
    //         ->group('i.productid, i.wid, i.arrival_date, i.is_futures')
    //         ->where($where)
    //         ->having('quantity > 0');


    //     $total = $model->count(); // 获取总数
    //     $result = $model->select(); // 获取查询结果
    //     $data = $result->toArray(); // 转换为数组

    //     // 格式化数据
    //     $format = [];
    //     foreach ($data as $datum) {
    //         $wid_arr = explode(',', $datum['wid']);
    //         if (count($wid_arr) == 1) {
    //             $key = $datum['product_id'] . '_' . $datum['arrival_date'] . '_' . $datum['is_futures'] . '_' . $datum['wid'];
    //             if (isset($format[$key])) {
    //                 $format[$key]['quantity'] += $datum['quantity'];
    //             } else {
    //                 $fake = $datum;
    //                 $fake['wid'] = reset($wid_arr);
    //                 $format[$key] = $fake;
    //             }
    //         } else {
    //             foreach ($wid_arr as $wid) {
    //                 $key = $datum['product_id'] . '_' . $datum['arrival_date'] . '_' . $datum['is_futures'] . '_' . $wid;
    //                 if (isset($format[$key])) {
    //                     $format[$key]['quantity'] += $datum['quantity'];
    //                 } else {
    //                     $fake = $datum;
    //                     $fake['wid'] = $wid;
    //                     $fake['share_id'] = $datum['inventory_ids'];
    //                     $format[$key] = $fake;
    //                 }
    //             }
    //         }
    //     }
    //     // 获取币种信息
    //     $customerPaymentCurrencyData = Db::table('db_transaction_currency')->where('id', $currency)->field('abbr,name,id')->find(); // 客户选定的币种信息
    //     $usdCurrencyData = Db::table('db_transaction_currency')->where('id', 214)->field('abbr,name')->find(); // 美金币种信息


    //     // 获取所有库存ID的价格数据
    //     $allInventoryIds = [];
    //     foreach ($format as $item) {
    //         array_push($allInventoryIds,  explode(',', $item['inventory_ids'])[0]); //  productid, wid, arrival_date, is_futures 分组后每组的价格是相同的，所以只取第一个
    //     }

    //     $allInventoryIds = array_unique($allInventoryIds);

    //     // 批量查询所有价格信息
    //     $pricesData = ProductPriceModel::with(
    //         [
    //             'discount' => function ($query) {
    //                 $query->field('id, num, price , price_id , level'); // 指定关联表字段，必须包含外键 price_id
    //             }
    //         ]
    //     )
    //         ->whereIn('inventory_id', $allInventoryIds)
    //         ->where('transaction_currency_id', $currency)
    //         ->field('id,
    //         inventory_id,
    //         transaction_currency_id, price , "' .
    //             $customerPaymentCurrencyData['name'] . '" as actual_quoted_currency_name, "' .
    //             $customerPaymentCurrencyData['name'] . '" as customer_payment_currency_name') // 明确指定主表字段（避免字段与条件冲突）
    //         ->select()
    //         ->toArray();
    //     // 将 inventory_id 作为结果数组的键

    //     $pricesData = array_column($pricesData, null, 'inventory_id');
    //     $currencyPricesDataInventoryId = array_keys($pricesData); // 查询到默认价格的库存ID


    //     if ($currency != 214) {  // 如果需要查询美金价格（当前币种不是美金时）
    //         $dollarPricesDataInventoryId = array_diff($allInventoryIds, $currencyPricesDataInventoryId);
    //         $dollerPricesData =  ProductPriceModel::with(
    //             [
    //                 'discount' => function ($query) {
    //                     $query->field('id, num, price , price_id , level'); // 指定关联表字段，必须包含外键 price_id
    //                 }
    //             ]
    //         )
    //             ->whereIn('inventory_id', $dollarPricesDataInventoryId)
    //             ->where('transaction_currency_id', 214)
    //             ->field('id,
    //             inventory_id,
    //             transaction_currency_id, price , "' .
    //                 $usdCurrencyData['name'] . '" as actual_quoted_currency_name, "' .
    //                 $customerPaymentCurrencyData['name'] . '" as customer_payment_currency_name') // 明确指定主表字段（避免字段与条件冲突）
    //             ->select()
    //             ->toArray(); // 获取美金价格
    //         $pricesData = array_merge($pricesData, $dollerPricesData);
    //     }

    //     $pricesData = array_column($pricesData, null, 'inventory_id');


    //     // 获取汇率 API 实例
    //     $fetcher = new ExchangeRateHostAPI();
    //     $exchange_rate = $fetcher->getRate($usdCurrencyData['abbr'], $customerPaymentCurrencyData['abbr']);

    //     // 循环处理库存数据，匹配价格信息
    //     foreach ($format as $key => &$value) {
    //         // 获取当前库存组的第一个 inventory_id
    //         $inventory_id = explode(',', $value['inventory_ids'])[0];

    //         // 检查是否有对应的价格数据
    //         if (!isset($pricesData[$inventory_id])) {
    //             unset($format[$key]); // 如果没有价格数据，过滤掉
    //             continue;
    //         }

    //         // 获取价格数据
    //         $priceInfo = $pricesData[$inventory_id];

    //         $price_ids = [$priceInfo['id']]; // 价格ID集合
    //         $price_values = [$priceInfo['price']]; // 价格集合

    //         // 设置价格相关字段
    //         $value['prices'] = implode(',', $price_values); // 价格字符串
    //         $value['price_ids'] = implode(',', $price_ids); // 价格ID字符串
    //         $value['original_price'] = reset($price_values); // 原价
    //         $value['actual_price'] = reset($price_values); // 实际价格
    //         $value['original_actual_price'] = reset($price_values); // 原始实际价格
    //         $value['actual_quoted_currency_name'] =  $priceInfo['actual_quoted_currency_name']; // 实际价格币种名称
    //         $value['customer_payment_currency_name'] =  $priceInfo['customer_payment_currency_name']; // 客户支付币种名称
    //         $value['actual_quoted_currency'] = $priceInfo['transaction_currency_id'];

    //         // 处理折扣信息
    //         $value['discount_price'] = [];
    //         if (!empty($priceInfo['discount'])) {
    //             $discount = $priceInfo['discount'];
    //             foreach ($discount as &$discount_price) {
    //                 if ($discount_price['level'] == 1) {
    //                     $value['actual_price'] = $discount_price['price']; // 更新实际价格
    //                 }
    //                 if ($priceInfo['transaction_currency_id'] != $currency) {
    //                     // 客户选定的币种 != 库存报价币种，计算实际售卖折扣价格
    //                     $discount_price['discount_actual_selling_price'] = round($discount_price['price'] * $exchange_rate, 2);
    //                 } else {
    //                     $discount_price['discount_actual_selling_price'] = $discount_price['price'];
    //                 }
    //             }
    //             $value['discount_price'] = $discount; // 折扣信息
    //         }

    //         // 计算实际售卖价格
    //         if ($priceInfo['transaction_currency_id'] == $currency) {
    //             // 客户选定的币种 == 库存报价币种
    //             $value['original_actual_selling_price'] = $value['original_price']; // 原始客户付款币种价格
    //             $value['actual_selling_price'] = $value['actual_price']; // 实际客户付款币种价格
    //         } else {
    //             // 客户选定的币种 != 库存报价币种，需要汇率转换

    //             $value['original_actual_selling_price'] = round($value['original_price'] * $exchange_rate, 2); // 原始客户付款币种价格
    //             $value['actual_selling_price'] = round($value['actual_price'] * $exchange_rate, 2); // 实际客户付款币种价格
    //         }

    //         // 设置唯一标识
    //         $value['unique'] = $value['product_id'] . '_' . $value['arrival_date'] . '_' . $value['is_futures'] . '_' . $value['wid'];
    //     }

    //     // 处理仓库信息
    //     $warehouse_arr = [];
    //     foreach ($format as $item) {
    //         $warehouse_arr[] = $item['wid'];
    //     }
    //     $warehouse_arr = array_unique($warehouse_arr);

    //     // 查询仓库的 fl_warehouse_id
    //     $fl_data = WarehouseModel::whereIn('id', $warehouse_arr)->column('fl_warehouse_id', 'id');
    //     foreach ($format as &$item) {
    //         $item['fl_warehouse_id'] = $fl_data[$item['wid']] ?? $item['wid']; // 如果 fl_warehouse_id 不存在，则使用 wid
    //     }

    //     // 返回结果
    //     $format = ['list' => array_values($format), 'total' => $total];
    //     return ['code' => 0, 'message' => 'success', 'data' => $format];
    // }

    /**
     * 合并库存 商品报价已经更新，新的数据在Product Price Service中
     * @param $param
     * @param $page
     * @param $limit
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * 2024-11-08 13 34 31
     * author: jiang
     */
    // public function merge($param, $page = 1, $limit = 10)
    // {
    //     $where = [['i.is_del', '=', 0]];
    //     if ($param['type'] == 1) {
    //         $where[] = ['i.is_sale', '=', 1];
    //     }
    //     $currency = $param['currency'] ?? 214;
    //     if (isset($param['product']) && $param['product']) {
    //         $where[] = ['p.cname', 'like', '%' . $param['product'] . '%'];
    //     }
    //     if ($param['wid']) {
    //         $where[] = ['i.wid', '=', $param['wid']];
    //     }
    //     if ($param['brand']) {
    //         $where[] = ['p.brand', '=', $param['brand']];
    //     }
    //     if ($param['is_futures'] != null) {
    //         $where[] = ['i.is_futures', '=', $param['is_futures']];
    //     }
    //     if ($param['start_date']) {
    //         $where[] = ['i.arrival_date', '>=', $param['start_date']];
    //     }
    //     if ($param['end_date']) {
    //         $where[] = ['i.arrival_date', '<', $param['end_date']];
    //     }

    //     $model = Db::table('db_inventory')
    //         ->alias('i')
    //         ->field([
    //             'i.productid as product_id',
    //             'i.arrival_date',
    //             'i.is_futures',
    //             'i.wid',
    //             'p.cname as product_name',
    //             'p.code as product_code',
    //             'p.expiration_date',
    //             'p.brand',
    //             'p.hashrate',
    //             'p.free_shipping',
    //             'p.apply_rules',
    //             'SUM(i.available_qty - i.lock_qty) as quantity',
    //             'MAX(price.id) as max_price_id', // 新增聚合字段
    //             'GROUP_CONCAT(price.price) as prices',
    //             'GROUP_CONCAT(i.id) as inventory_ids',
    //             'SUBSTRING_INDEX(GROUP_CONCAT(price.id order by price.id desc), ",", 1) as price_id',
    //             'max(i.allow_zero_stock_sale) as allow_zero_stock_sale'
    //         ])
    //         ->leftJoin('db_product p', 'i.productid = p.id')
    //         ->leftJoin('db_product_price price', 'price.inventory_id = i.id and price.transaction_currency_id = ' . $currency)
    //         ->group('i.productid, i.wid, i.arrival_date, i.is_futures')
    //         ->where($where);
    //     if ($param['type'] == 1) {
    //         $model = $model->having('prices IS NOT NULL AND prices != ""')
    //             ->having('price_id IS NOT NULL AND price_id != ""');
    //     }
    //     $model = $model->order('max_price_id desc');
    //     $total = $model->count();
    //     $result = $model->select();
    //     // 格式化
    //     $data = $result->toArray();
    //     $format = [];
    //     foreach ($data as $datum) {
    //         $wid_arr = explode(',', $datum['wid']);
    //         if (count($wid_arr) == 1) {
    //             $key = $datum['product_id'] . '_' . $datum['arrival_date'] . '_' . $datum['is_futures'] . '_' . $datum['wid'];
    //             if (isset($format[$key])) {
    //                 $format[$key]['quantity'] += $datum['quantity'];
    //             } else {
    //                 $fake = $datum;
    //                 $fake['wid'] = reset($wid_arr);
    //                 $format[$key] = $fake;
    //             }
    //         } else {
    //             foreach ($wid_arr as $wid) {
    //                 $key = $datum['product_id'] . '_' . $datum['arrival_date'] . '_' . $datum['is_futures'] . '_' . $wid;
    //                 //如果数组已存在
    //                 if (isset($format[$key])) {
    //                     $format[$key]['quantity'] += $datum['quantity'];
    //                 } else {
    //                     $fake = $datum;
    //                     $fake['wid'] = $wid;
    //                     $fake['share_id'] = $datum['inventory_ids'];
    //                     $format[$key] = $fake;
    //                 }
    //             }
    //         }
    //     }


    //     $price_ids = [];
    //     foreach ($format as $price) {
    //         if ($price['price_id']) {
    //             $price_ids[] = $price['price_id'];
    //         }
    //     }
    //     $oProductDiscountModel = ProductDiscountModel::whereIn('price_id', array_unique($price_ids))->column('num,rate,price,level,price_id');
    //     $price_dec = [];
    //     foreach ($oProductDiscountModel as $item) {
    //         $price_dec[$item['price_id']] = $item;
    //     }
    //     foreach ($format as $key => &$value) {
    //         if ($value['quantity'] == 0 && $value['allow_zero_stock_sale'] != 1) {
    //             unset($format[$key]);
    //             continue;
    //         }
    //         $prices = $value['prices'] ?? '';
    //         $price_arr = explode(',', $prices);
    //         $value['original_price'] = reset($price_arr);
    //         $value['actual_price'] = reset($price_arr);
    //         $value['original_actual_price'] = reset($price_arr);
    //         unset($value['prices']);
    //         $value['wid'] = (int)$value['wid'];
    //         $value['brand'] = (int)$value['brand'];
    //         // 获取折扣信息
    //         $inventory_arr = $value['inventory_ids'] ? explode(',', $value['inventory_ids']) : [];
    //         $value['inventory_id'] = reset($inventory_arr);
    //         $value['currency'] = $currency;
    //         $value['discount_price'] = isset($price_dec[$value['price_id']]) ? [$price_dec[$value['price_id']]] : [];
    //         foreach ($value['discount_price'] as $discount_price) {
    //             if ($discount_price['level'] == 1) {
    //                 $value['actual_price'] = $discount_price['price'];
    //             }
    //         }
    //         // 唯一标识
    //         $value['unique'] = $value['product_id'] . '_' . $value['arrival_date'] . '_' . $value['is_futures'] . '_' . $value['wid'];
    //     }

    //     $warehouse_arr = [];
    //     foreach ($format as $jer) {
    //         $warehouse_arr[] = $jer['wid'];
    //     }
    //     $fl_data = WarehouseModel::whereIn('id', array_unique($warehouse_arr))->column('fl_warehouse_id,id');
    //     $fl_disc = [];
    //     foreach ($fl_data as $disc) {
    //         $fl_disc[$disc['id']] = $disc['fl_warehouse_id'];
    //     }
    //     foreach ($format as &$oper) {
    //         if ($fl_disc[$oper['wid']] === null) {
    //             $oper['fl_warehouse_id'] = $oper['wid'];
    //         } else {
    //             $oper['fl_warehouse_id'] = $fl_disc[$oper['wid']];
    //         }
    //     }
    //     $format = ['list' => array_values($format), 'total' => $total];
    //     return ['code' => 0, 'message' => 'success', 'data' => $format];
    // }

    /**
     * 获取资源
     * @param $param
     * @return array
     * 2024-11-08 13 30 21
     * author: jiang
     */
    public function resource($field)
    {
        $model = new InventoryModel();
        $enum = $model->getFieldEnum($field);
        if ($field === 'ALL') {
            $warehouse = $enum['wid'];
            $first_level = [];
            foreach ($warehouse as $key => $value) {
                if (empty($value['fl_warehouse_id'])) {
                    $first_level[] = $value;
                    unset($warehouse[$key]);
                }
            }

            foreach ($first_level as $jer => $item) {
                foreach ($warehouse as $op) {
                    if ($item['value'] == $op['fl_warehouse_id']) {
                        $first_level[$jer]['children'][] = $op;
                    }
                }
            }
            $enum['level_warehouse'] = $first_level;
        }
        return ['code' => 0, 'message' => 'success', 'data' => $enum];
    }

    /**
     * 导入价格
     * @param $param
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * 2024-12-05 13 41 01
     * author: jiang
     */
    public function importPrice($param)
    {
        $file = $param['file'];
        if (!$file) {
            return ['code' => 1, 'message' => '没有文件上传'];
        }
        $data = ExcelService::importFromUpload($file);
        if (isset($data['error']) && $data['error']) {
            return ['code' => 1, 'message' => $data['error']];
        }
        $expectedHeaders = [
            "商品名称",
            "sku",
            "仓库",
            "类型",
            "批次",
            "到货日期",
            "USD价格",
            "USD头程物流费",
            "USD数量(折扣等级1)",
            "USD折扣价格(折扣等级1)",
            "USD数量(折扣等级2)",
            "USD折扣价格(折扣等级2)",
            "USD数量(折扣等级3)",
            "USD折扣价格(折扣等级3)",
            "USD数量(折扣等级4)",
            "USD折扣价格(折扣等级4)",
            "USD数量(折扣等级5)",
            "USD折扣价格(折扣等级5)",
            "CNY价格",
            "CNY头程物流费",
            "CNY数量(折扣等级1)",
            "CNY折扣价格(折扣等级1)",
            "CNY数量(折扣等级2)",
            "CNY折扣价格(折扣等级2)",
            "CNY数量(折扣等级3)",
            "CNY折扣价格(折扣等级3)",
            "CNY数量(折扣等级4)",
            "CNY折扣价格(折扣等级4)",
            "CNY数量(折扣等级5)",
            "CNY折扣价格(折扣等级5)"
        ];
        $header = array_shift($data);
        if ($expectedHeaders != $header) {
            return ['code' => 1, 'message' => '文件格式不正确'];
        }
        $result_info = [];
        $format = [];
        foreach ($data as $jer => $datum) {
            if(!$datum[0] || !$datum[1] || !$datum[2] || !$datum[3]){
                continue;
            }
            $temp = [
                'product_name' => $datum[0],
                'sku' => $datum[1],
                'warehouse_name' => $datum[2],
                'is_futures_name' => $datum[3],
                'arrival_date' => $datum[5],
                'USD_price' => $datum[6],
                'CNY_price' => $datum[18],
                'inbound_batch' => $datum[4],
                'discount' => [],
                'USD_first_leg_fee' => $datum[7],
                'CNY_first_leg_fee' => $datum[19]
            ];
            // USD价格
            $level = 1;
            for ($i = 8; $i < 17; $i += 2) {
                $num = $datum[$i];
                $sales_price = $datum[$i + 1];

                if (!$num || !$sales_price) {
                    continue;
                }
                $temp['discount'][214][] = [
                    'level' => $level,
                    'num' => $num,
                    'sales_price' => $sales_price
                ];
                $level++;
            }
            // CNY价格
            $level2 = 1;
            for ($i = 20; $i < 30; $i += 2) {
                $num = $datum[$i];
                $sales_price = $datum[$i + 1];

                if (!$num || !$sales_price) {
                    continue;
                }
                $temp['discount'][4][] = [
                    'level' => $level2,
                    'num' => $num,
                    'sales_price' => $sales_price
                ];
                $level2++;
            }

            $key = $datum[0] . '_' . $datum[1] . '_' . $datum[2] . '_' . $datum[3];
            $format[$key] = $temp;

            $result_info[] = [
                'row' => $jer + 1,
                'info' => '',
                'identification' => $key // 标识
            ];
        }

        $enum = InventoryModel::getStaticEnum();
        $is_futures_text = $enum['is_futures_text'];
        foreach ($format as $pot => $item) {
            if (!isset($is_futures_text[$item['is_futures_name']])) {
                return ['code' => 1, 'message' => '商品类型不正确'];
            }

            $is_futures = $is_futures_text[$item['is_futures_name']];
            $where = [
                ['p.cname', '=', $item['product_name']],
                ['p.sku', '=', $item['sku']],
                ['w.name', '=', $item['warehouse_name']],
                ['i.arrival_date', '=', $item['arrival_date']],
                ['i.is_futures', '=', $is_futures]
            ];
            // 获取商品id
            $oInventory = DB::table('db_inventory')->alias('i')
                ->join('db_product p', 'i.productid = p.id')
                ->join('db_warehouse w', 'i.wid = w.id')
                ->where($where)
                ->field('i.id as inventory_id,wid')
                ->find();
            $isAdd = is_null($oInventory);
            if (!$oInventory) {
                // 如果商品不存在则新建
                $oProductModel = ProductModel::where('cname', '=', $item['product_name'])->find();
                if (!$oProductModel) {
                    continue;
                }
                $oWarehouseModel = WarehouseModel::where('name', $item['warehouse_name'])->where('fl_warehouse_id', 'exp', 'IS NULL')->find();
                if (!$oWarehouseModel) {
                    continue;
                }

                $oInventoryModel = new InventoryModel();
                $oInventoryModel->productid = $oProductModel->id;
                $oInventoryModel->wid = $oWarehouseModel->id;
                $oInventoryModel->source_table = 'inventory';
                $oInventoryModel->source_id = 0;
                $oInventoryModel->initial_qty = 0;
                $oInventoryModel->convertible_qty = 0;
                $oInventoryModel->available_qty = 0;
                $oInventoryModel->lock_qty = 0;
                $oInventoryModel->arrival_date = empty($item['arrival_date']) ? null : $item['arrival_date'];
                $oInventoryModel->inbound_batch = $item['inbound_batch'];
                $oInventoryModel->is_futures = $is_futures;
                $oInventoryModel->is_sale = 1;
                $oInventoryModel->creator = $param['operator_id'];
                $oInventoryModel->create_time = date('Y-m-d H:i:s');
                $oInventoryModel->remark = '提篮子商品报价';
                $oInventoryModel->allow_zero_stock_sale = 1;
                $oInventoryModel->if_tlz = 1;
                if (!$oInventoryModel->save()) {
                    $result_info = $this->handleImportResult($result_info, $pot, '商品创建失败');
                    continue;
                }
                //                $result_info = $this->handleImportResult($result_info, $pot, '商品不存在');
                //                continue;
                $oInventoryModel->inventory_id = $oInventoryModel->id;
                $oInventory = $oInventoryModel;
            }

            // 修改USD报价
            if (isset($item['discount'][214])) {
                // 拼接参数
                $handle = [
                    'operator_id' => $param['operator_id'],
                    'id' => $oInventory['inventory_id'],
                    'wid' => $oInventory['wid'],
                    'discount' => $item['discount'][214],
                    'currency' => 214,
                    'first_leg_logistics_fee' => $item['USD_first_leg_fee'],
                    'sales_price' => $item['USD_price']
                ];
                $result = $this->savePrice($handle);
            }
            // 修改CNY报价
            if (isset($item['discount'][4])) {
                // 拼接参数
                $handle = [
                    'operator_id' => $param['operator_id'],
                    'id' => $oInventory['inventory_id'],
                    'discount' => $item['discount'][4],
                    'wid' => $oInventory['wid'],
                    'currency' => 4,
                    'first_leg_logistics_fee' => $item['CNY_first_leg_fee'],
                    'sales_price' => $item['CNY_price']
                ];
                $result = $this->savePrice($handle);
            }

            if ($result['code'] != 0) {
                $result_info = $this->handleImportResult($result_info, $pot, $result['message']);
                continue;
            }
            $result_info = $this->handleImportResult($result_info, $pot, $isAdd ? '新增成功' : '更新成功');
        }
        return ['code' => 0, 'message' => 'success', 'data' => $result_info];
    }

    public function handleImportResult($result_info, $identification, $info)
    {
        foreach ($result_info as &$item) {
            if ($item['identification'] == $identification) {
                $item['info'] = $info;
            }
        }
        return $result_info;
    }

    /**
     * 导出价格
     * @param $param
     * @return void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * 2024-12-05 18 06 51
     * author: jiang
     */
    public function exportPrice($param)
    {
        $where = [];
        if (isset($param['is_futures']) && in_array($param['is_futures'], [0, 1, 2]) ) {
            $where[] = ['i.is_futures', '=', $param['is_futures']];
        }
        $warehouseFilterId = null;
        if (!empty($param['warehouse_name'])) {
            $warehouseFilterId = $param['warehouse_name'];
        }
        if (!empty($param['arrival_date'])) {
            $where[] = ['i.arrival_date', '=', $param['arrival_date']];
        }
        if (!empty($param['source_table'])) {
            $where[] = ['i.source_table', '=', $param['source_table']];
        }
        if (isset($param['name']) && $param['name']) {
            $where[] = ['p.cname', 'like', '%' . $param['name'] . '%'];
        }

        $baseList = DB::table('db_inventory i')
            ->join('db_product p', 'i.productid = p.id')
            ->field([
                'i.id as inventory_id',
                'p.cname as product_name',
                'p.sku',
                'p.id as product_id',
                'i.wid as warehouse_id',
                'i.available_qty - i.lock_qty as quantity',
                "CASE i.is_futures
                         WHEN 0 THEN '现货'
                         WHEN 1 THEN '在途期货'
                         WHEN 2 THEN '大期货'
                         ELSE '未知类型' END as is_futures",
                'i.inbound_batch',
                'i.arrival_date',
            ])
            ->whereRaw("i.available_qty > 0 OR i.allow_zero_stock_sale = 1")
            ->where('i.is_del', '=', 0)
            ->where($where)
            ->when(!empty($warehouseFilterId), function ($query) use ($warehouseFilterId) {
                $query->whereRaw('FIND_IN_SET(?, i.wid)', [$warehouseFilterId]);
            })
            ->select()->toArray();

        if (empty($baseList)) {
            $header = [
                "商品名称",
                "sku",
                "仓库",
                "类型",
                "批次",
                "到货日期",
                "USD价格",
                "USD头程物流费",
                "USD数量(折扣等级1)",
                "USD折扣价格(折扣等级1)",
                "USD数量(折扣等级2)",
                "USD折扣价格(折扣等级2)",
                "USD数量(折扣等级3)",
                "USD折扣价格(折扣等级3)",
                "USD数量(折扣等级4)",
                "USD折扣价格(折扣等级4)",
                "USD数量(折扣等级5)",
                "USD折扣价格(折扣等级5)",
                "CNY价格",
                "CNY头程物流费",
                "CNY数量(折扣等级1)",
                "CNY折扣价格(折扣等级1)",
                "CNY数量(折扣等级2)",
                "CNY折扣价格(折扣等级2)",
                "CNY数量(折扣等级3)",
                "CNY折扣价格(折扣等级3)",
                "CNY数量(折扣等级4)",
                "CNY折扣价格(折扣等级4)",
                "CNY数量(折扣等级5)",
                "CNY折扣价格(折扣等级5)"
            ];
            ExcelService::export([], $header, 'exportPrice.xlsx');
            return;
        }

        $inventoryIds = array_column($baseList, 'inventory_id');

        $allWarehouseIds = [];
        foreach ($baseList as $row) {
            if (!empty($row['warehouse_id'])) {
                foreach (explode(',', (string)$row['warehouse_id']) as $wid) {
                    $wid = trim($wid);
                    if ($wid !== '') { $allWarehouseIds[$wid] = true; }
                }
            }
        }
        $warehouseIdToName = [];
        if (!empty($allWarehouseIds)) {
            $idList = array_keys($allWarehouseIds);
            $warehouseRows = DB::table('db_warehouse')
                ->field(['id','name'])
                ->whereIn('id', $idList)
                ->select()->toArray();
            foreach ($warehouseRows as $wr) {
                $warehouseIdToName[(string)$wr['id']] = $wr['name'];
            }
        }

        $priceList = DB::table('db_product_price')
            ->field([
                'id as price_id',
                'inventory_id',
                'transaction_currency_id',
                'price',
                'first_leg_logistics_fee',
            ])
            ->whereIn('inventory_id', $inventoryIds)
            ->where('is_del', '=', 0)
            ->select()->toArray();

        $priceIds = $priceList ? array_column($priceList, 'price_id') : [];

        $discountList = [];
        if (!empty($priceIds)) {
            $discountList = DB::table('db_product_discount')
                ->field([
                    'id as discount_id',
                    'price_id',
                    'level',
                    'num',
                    'price as discount_price',
                    'rate',
                ])
                ->whereIn('price_id', $priceIds)
                ->select()->toArray();
        }

        $priceIdToDiscounts = [];
        foreach ($discountList as $d) {
            $priceId = $d['price_id'];
            if (!isset($priceIdToDiscounts[$priceId])) {
                $priceIdToDiscounts[$priceId] = [];
            }
            $priceIdToDiscounts[$priceId][] = [
                'discount_id' => $d['discount_id'],
                'level' => $d['level'],
                'num' => $d['num'],
                'discount_price' => $d['discount_price'],
                'rate' => $d['rate'],
            ];
        }

        $inventoryIdToPrices = [];
        foreach ($priceList as $p) {
            $invId = $p['inventory_id'];
            if (!isset($inventoryIdToPrices[$invId])) {
                $inventoryIdToPrices[$invId] = [];
            }
            $inventoryIdToPrices[$invId][] = [
                'transaction_currency_id' => $p['transaction_currency_id'],
                'price' => $p['price'],
                'price_id' => $p['price_id'],
                'first_leg_logistics_fee' => $p['first_leg_logistics_fee'],
                // 使用用户期望的 key 名称 "dicount"（保持示例一致）
                'dicount' => isset($priceIdToDiscounts[$p['price_id']]) ? $priceIdToDiscounts[$p['price_id']] : [],
            ];
        }

        $grouped = [];
        foreach ($baseList as $base) {
            $warehouseNames = [];
            if (!empty($base['warehouse_id'])) {
                foreach (explode(',', (string)$base['warehouse_id']) as $wid) {
                    $wid = trim($wid);
                    if ($wid === '') { continue; }
                    if (isset($warehouseIdToName[$wid])) {
                        $warehouseNames[] = $warehouseIdToName[$wid];
                    }
                }
            }
            $grouped[] = [
                'inventory_id' => $base['inventory_id'],
                'product_name' => $base['product_name'],
                'sku' => $base['sku'],
                'product_id' => $base['product_id'],
                'warehouse_name' => empty($warehouseNames) ? '' : implode(',', $warehouseNames),
                'warehouse_id' => $base['warehouse_id'],
                'is_futures' => $base['is_futures'],
                'inbound_batch' => $base['inbound_batch'],
                'arrival_date' => $base['arrival_date'],
                'price' => isset($inventoryIdToPrices[$base['inventory_id']]) ? $inventoryIdToPrices[$base['inventory_id']] : [],
            ];
        }

        $header = [
            "商品名称",
            "sku",
            "仓库",
            "类型",
            "批次",
            "到货日期",
            "USD价格",
            "USD头程物流费",
            "USD数量(折扣等级1)",
            "USD折扣价格(折扣等级1)",
            "USD数量(折扣等级2)",
            "USD折扣价格(折扣等级2)",
            "USD数量(折扣等级3)",
            "USD折扣价格(折扣等级3)",
            "USD数量(折扣等级4)",
            "USD折扣价格(折扣等级4)",
            "USD数量(折扣等级5)",
            "USD折扣价格(折扣等级5)",
            "CNY价格",
            "CNY头程物流费",
            "CNY数量(折扣等级1)",
            "CNY折扣价格(折扣等级1)",
            "CNY数量(折扣等级2)",
            "CNY折扣价格(折扣等级2)",
            "CNY数量(折扣等级3)",
            "CNY折扣价格(折扣等级3)",
            "CNY数量(折扣等级4)",
            "CNY折扣价格(折扣等级4)",
            "CNY数量(折扣等级5)",
            "CNY折扣价格(折扣等级5)"
        ];
        $data = [];
        foreach ($grouped as $g) {
            $row = [
                $g['product_name'],
                $g['sku'],
                $g['warehouse_name'],
                $g['is_futures'],
                $g['inbound_batch'],
                $g['arrival_date'],
            ];

            // 提取 USD 与 CNY 的价格与折扣
            $usdPrice = null;
            $cnyPrice = null;
            foreach ($g['price'] as $p) {
                if ($p['transaction_currency_id'] == 214) {
                    $usdPrice = $p;
                } elseif ($p['transaction_currency_id'] == 4) {
                    $cnyPrice = $p;
                }
            }

            // USD 列
            $row[] = $usdPrice ? $usdPrice['price'] : '';
            $row[] = $usdPrice ? $usdPrice['first_leg_logistics_fee'] : '';
            $usdDiscounts = $usdPrice ? $usdPrice['dicount'] : [];
            // 以 level 排序并填充 1..5
            $usdByLevel = [];
            foreach ($usdDiscounts as $d) { $usdByLevel[$d['level']] = $d; }
            for ($i = 1; $i <= 5; $i++) {
                if (isset($usdByLevel[$i])) {
                    $row[] = $usdByLevel[$i]['num'];
                    $row[] = $usdByLevel[$i]['discount_price'];
                } else {
                    $row[] = '';
                    $row[] = '';
                }
            }

            // CNY 列
            $row[] = $cnyPrice ? $cnyPrice['price'] : '';
            $row[] = $cnyPrice ? $cnyPrice['first_leg_logistics_fee'] : '';
            $cnyDiscounts = $cnyPrice ? $cnyPrice['dicount'] : [];
            $cnyByLevel = [];
            foreach ($cnyDiscounts as $d) { $cnyByLevel[$d['level']] = $d; }
            for ($i = 1; $i <= 5; $i++) {
                if (isset($cnyByLevel[$i])) {
                    $row[] = $cnyByLevel[$i]['num'];
                    $row[] = $cnyByLevel[$i]['discount_price'];
                } else {
                    $row[] = '';
                    $row[] = '';
                }
            }

            $data[] = $row;
        }

        ExcelService::export($data, $header, 'exportPrice.xlsx');
    }

    /**
     *   锁定库存
     */
    public function locking($data, $type = null)
    {
        foreach ($data as $value) {
            $quantity = $value['quantity'];

            // 查询具体库存记录，并加锁
            $inventoryList = Db::name('inventory')
                ->field('id,productid,wid,arrival_date,is_futures,available_qty,lock_qty')
                ->whereFindInSet('wid', $value['warehouse_id'])
                ->where([
                    'is_del' => 0,
                    'is_sale' => 1,
                    'productid' => $value['product_id'],
                    'arrival_date' => $value['arrival_date'],
                    'is_futures' => $value['is_futures'],
                    ['available_qty', '>', 0],
                ])
                ->lock(true)
                ->select();

            foreach ($inventoryList as $key => $inventory) {

                if ($quantity <= 0) {
                    break;
                }

                $keyongkucun = $inventory['available_qty'] - $inventory['lock_qty'];
                if ($quantity <= $keyongkucun) {
                    $lockQty = $quantity;
                    $quantity = 0;
                } else {
                    $lockQty = $keyongkucun;
                    $quantity -= $keyongkucun;
                }

                // 更新锁定库存
                Db::name('inventory')
                    ->where('id', $inventory['id'])
                    ->inc('lock_qty', $lockQty)
                    ->update();
            }

            // 如果最终的 buynum 不为 0，则说明库存不足，回滚事务
            if ($quantity > 0) {
                throw new Exception('库存不足');
            }
        }
        return true;
    }

    public function unlock($data, $order_type)
    {
        foreach ($data['item'] as $value) {

            $count_quantity = $value['quantity'];

            // 查询具体库存记录，并加锁
            $inventoryList = Db::name('inventory')
                ->field('id,productid,wid,arrival_date,is_futures,available_qty,lock_qty')
                ->whereFindInSet('wid', $value['warehouse_id'])
                ->where([
                    'is_del' => 0,
                    'is_sale' => 1,
                    'productid' => $value['product_id'],
                    'arrival_date' => $value['arrival_date'],
                    'is_futures' => $value['is_futures']
                ])
                ->lock(true)
                ->select();

            foreach ($inventoryList as $key => $inventory) {

                if ($count_quantity <= 0) {
                    break;
                }

                $lock_item_qty = $inventory['lock_qty'];

                if ($count_quantity <= $lock_item_qty) {
                    $lockQty = $count_quantity;
                    $count_quantity = 0;
                } else {
                    $lockQty = $lock_item_qty;
                    $count_quantity = $count_quantity - $lock_item_qty;
                }

                // 更新锁定库存
                Db::name('inventory')
                    ->where('id', $inventory['id'])
                    ->dec('lock_qty', $lockQty)
                    ->update();
            }
        }

        return true;
    }

    public function Inventorylocking($order, $type)
    {
        switch ($type) {
            case 'order':
                $orderItem = OrderItem::where('order_id', $order->id)->field('quantity,product_id,warehouse_id,arrival_date,is_futures')->select();
                break;
            case 'wholesale':
                $orderItem = WholesalOrderItem::where('order_id', $order->id)->field('id,quantity,product_id,warehouse_id,arrival_date,is_futures')->select();
                break;

            default:
                throw new Exception(
                    '锁定库存，订单类型错误'
                );
        }
        return $this->locking($orderItem, $type);
    }

    public function InventoryUnlocking($order, $type)
    {
        switch ($type) {
            case 'order':
                $result = ModelOrder::with([
                    'item' => function ($query) {
                        $query->with([])->field('order_id,product_id,warehouse_id,quantity,arrival_date,is_futures');
                    },
                ])->where('id', $order->id)->find();
                break;
            case 'wholesale':
                $result = WholesalOrder::with([
                    'item' => function ($query) {
                        $query->with([])->field('order_id,product_id,warehouse_id,quantity,arrival_date,is_futures');
                    },
                ])->where('id', $order->id)->find();
                break;

            default:
                throw new Exception(
                    '释放库存，订单类型错误'
                );
        }
        return $this->unlock($result, $type);
    }

    /**
     * 订单转换库存
     * @param $param
     * @return array|void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * 2024-12-25 18 39 01
     * author: jiang
     */
    public function transSaveByOrder($param)
    {
        $inventoryLogic = new InventoryTransSave();
        return $inventoryLogic->transSaveByOrder($param);
        // Db::startTrans();
        // try {
        //     $oOrderItemModel = OrderItemModel::where('is_futures', '<>', 0)->find($param['id']);
        //     if (!$oOrderItemModel) {
        //         return ['code' => 1, 'message' => '未找到订单信息！'];
        //     }
        //     // 计算需要转换的总数量
        //     $need_trans_quantity = array_sum(array_column($param['list'], 'quantity'));


        //     // 查询可转换数量
        //     $where = [
        //         ['productid', '=', $param['productid']],
        //         ['arrival_date', '=', null],
        //         ['is_futures', '=', 0],
        //         ['is_del', '=', 0],
        //         ['id', 'in', array_column($param['list'], 'id')]
        //     ];
        //     $warehouse = WarehouseModel::where('id', '=', $param['wid'])->field('fl_warehouse_id')->find();
        //     if ($warehouse['fl_warehouse_id'] != null) {
        //         $where[] = ['wid', '=', $param['wid']];
        //     } else {
        //         $warehouse_ids = WarehouseModel::where('fl_warehouse_id', '=', $param['wid'])->column('id');
        //         $where[] = ['wid', 'in', $warehouse_ids];
        //     }
        //     $InventoryArr = InventoryModel::where($where)
        //         ->whereRaw('(available_qty - lock_qty) > ?', [0])
        //         ->field([
        //             'available_qty - lock_qty as available_qty',
        //             'id',
        //             'purchase_currency',
        //             'purchase_price',
        //             'wid'
        //         ])
        //         ->select()
        //         ->toArray();
        //     $InventoryArr = array_column($InventoryArr, null, 'id');

        //     $newOrderItemModel = new OrderItemModel();
        //     foreach ($param['list'] as $jer) {
        //         $inventory = $InventoryArr[$jer['id']];
        //         if ($inventory['available_qty'] < $jer['quantity']) {
        //             throw new Exception('库存不足');
        //         } else {
        //             $resultUpdateOrderItem = $newOrderItemModel
        //                 ->where('id', $param['id'])
        //                 ->bind([
        //                     'dec_num1' => intval($jer['quantity']),
        //                     'dec_num2' => intval($jer['quantity'])
        //                 ])
        //                 ->update([
        //                     'quantity' => Db::raw('quantity - :dec_num1'),
        //                     'pending_quantity' => Db::raw('pending_quantity - :dec_num2'),
        //                 ]);

        //             if (!$resultUpdateOrderItem) {
        //                 throw new Exception('订单转换原始明细数据扣减失败');
        //             }

        //             $resultInsert = $newOrderItemModel->insert([
        //                 'user_id' => $oOrderItemModel->user_id,
        //                 'order_id' => $oOrderItemModel->order_id,
        //                 'product_id' => $oOrderItemModel->product_id,
        //                 'warehouse_id' => $inventory['wid'],
        //                 'original_price' => $oOrderItemModel->original_price,
        //                 'actual_price' => $oOrderItemModel->actual_price,
        //                 'quantity' => $jer['quantity'],
        //                 'creator' => $oOrderItemModel->creator,
        //                 'create_time' => date('Y-m-d H:i:s'),
        //                 'wholesal_id' => $oOrderItemModel->wholesal_id,
        //                 'is_futures' => 0,
        //                 'pending_quantity' => $jer['quantity'],
        //                 'is_advance' => $oOrderItemModel->is_advance,
        //                 'advance_ratio' => $oOrderItemModel->advance_ratio,
        //                 'transaction_currency_id' => $oOrderItemModel->transaction_currency_id,
        //                 'price_selected_currency' => $oOrderItemModel->price_selected_currency,
        //                 'purchase_currency' => $inventory['purchase_currency'],
        //                 'purchase_price' => $inventory['purchase_price']
        //             ]);
        //             if (!$resultInsert) {
        //                 throw new Exception('订单转换库存插入订单明细失败');
        //             }

        //             $resultUpdateInventory = InventoryModel::where('id', $inventory['id'])
        //                 ->whereRaw('available_qty - lock_qty >= :min_qty')
        //                 ->bind([
        //                     'min_qty' => intval($jer['quantity']),
        //                     'dec_num' => intval($jer['quantity'])
        //                 ])
        //                 ->update([
        //                     'lock_qty' => Db::raw('lock_qty + :dec_num'),
        //                     'update_time' => date('Y-m-d H:i:s')
        //                 ]);
        //             if (!$resultUpdateInventory) {
        //                 throw new Exception('订单库存类型转换库存锁定失败');
        //             }

        //             $inventoryService = new InventoryService();
        //             $unlock = $inventoryService->unlockInventory([[
        //                 'product_id' => $oOrderItemModel->product_id,
        //                 'arrival_date' => $oOrderItemModel->arrival_date,
        //                 'is_futures' => $oOrderItemModel->is_futures,
        //                 'wid' => $oOrderItemModel->warehouse_id,
        //                 'quantity' => $jer['quantity'],
        //             ]]);

        //             if (!$unlock) {
        //                 throw new Exception('订单库存类型转换库存解锁失败');
        //             }

        //             $need_trans_quantity = $need_trans_quantity - $jer['quantity'];
        //         }
        //     }
        //     if ($need_trans_quantity > 0) {
        //         throw new Exception('库存不足');
        //     }
        //     Db::commit();
        //     $orderInfo = Db::name('order')->where('id', $oOrderItemModel->order_id)->where('is_del',  0)->find();
        //     if (empty($oOrderItemModel->warehouse_code)) { // 订单自提
        //         $allOrderItem = OrderItemModel::where('order_id', $oOrderItemModel->order_id)->where('is_del',  0)->select(); // 全部订单明细

        //         $futures_num = 0;
        //         foreach ($allOrderItem as $item) {
        //             if ($item->is_futures != 0) {
        //                 $futures_num += $item->quantity;
        //             }
        //         }

        //         if ($futures_num == 0) {
        //             $mailService = new Mail();
        //             $orderInfo = Db::name('order')->where('id', $oOrderItemModel->order_id)->where('is_del',  0)->find();

        //             $mailService->send('self_pickup', [
        //                 'user_id' => $orderInfo['user_id'],
        //                 'order_no' => $orderInfo['order_no'],
        //             ]);
        //         }
        //     }
        // } catch (Exception $e) {
        //     Db::rollback();
        //     return ['code' => 1, 'message' => $e->getMessage()];
        // }
        // return ['code' => 0, 'message' => '订单转换库存成功'];
    }


    // public function transSaveByOrderOld($param)
    // {
    //     Db::startTrans();
    //     try {
    //         $oOrderItemModel = OrderItemModel::where('is_futures', '<>', 0)->find($param['id']);
    //         if (!$oOrderItemModel) {
    //             return ['code' => 1, 'message' => '未找到订单信息！'];
    //         }
    //         // 计算需要转换数量
    //         // 计算需要转换的总数量
    //         $need_trans_quantity = array_sum(array_column($param['list'], 'quantity'));

    //         // 查询可转换数量
    //         $where = [
    //             ['productid', '=', $param['productid']],
    //             ['arrival_date', '=', null],
    //             ['is_futures', '=', 0],
    //             ['is_del', '=', 0],
    //             ['id', 'in', array_column($param['list'], 'id')]
    //         ];
    //         $warehouse = WarehouseModel::where('id', '=', $param['wid'])->field('fl_warehouse_id')->find();
    //         if ($warehouse['fl_warehouse_id'] != null) {
    //             $where[] = ['wid', '=', $param['wid']];
    //         } else {

    //             $warehouse_ids = WarehouseModel::where('fl_warehouse_id', '=', $param['wid'])->column('id');
    //             $where[] = ['wid', 'in', $warehouse_ids];
    //         }
    //         $available_qty = 0;
    //         $InventoryArr = InventoryModel::where($where)
    //             ->whereRaw('(available_qty - lock_qty) > ?', [0])
    //             ->field([
    //                 'available_qty - lock_qty as available_qty',
    //                 'id',
    //                 'purchase_currency',
    //                 'purchase_price'
    //             ])
    //             ->select()
    //             ->toArray();
    //         $InventoryArr = array_column($InventoryArr, null, 'id');

    //         foreach ($InventoryArr as $item) {
    //             foreach ($param['list'] as $jer) {
    //                 if ($item['id'] == $jer['id'] && $item['available_qty'] < $jer['quantity']) {
    //                     throw new Exception('库存不足');
    //                 } else {
    //                 }
    //             }
    //             if ($item['available_qty'] > 0) {
    //                 $available_qty += $item['available_qty'];
    //             }
    //         }
    //         if ($available_qty < $need_trans_quantity) {
    //             return ['code' => 1, 'message' => '库存不足'];
    //         }

    //         if ($oOrderItemModel->quantity >= $need_trans_quantity) {
    //             // 部分转换
    //             $oOrderItemModel->quantity = $oOrderItemModel->quantity - $need_trans_quantity;
    //             $oOrderItemModel->pending_quantity = $oOrderItemModel->pending_quantity - $need_trans_quantity;

    //             if (!$oOrderItemModel->save()) {
    //                 return ['code' => 1, 'message' => '订单转换库存失败'];
    //             }
    //             $newOrderItemModel = new OrderItemModel();
    //             $newOrderItemModel->user_id = $oOrderItemModel->user_id;
    //             $newOrderItemModel->order_id = $oOrderItemModel->order_id;
    //             $newOrderItemModel->product_id = $oOrderItemModel->product_id;
    //             $newOrderItemModel->warehouse_id = $oOrderItemModel->warehouse_id;
    //             $newOrderItemModel->original_price = $oOrderItemModel->original_price;
    //             $newOrderItemModel->actual_price = $oOrderItemModel->actual_price;
    //             $newOrderItemModel->quantity = $need_trans_quantity;
    //             $newOrderItemModel->creator = $oOrderItemModel->creator;
    //             $newOrderItemModel->create_time = date('Y-m-d H:i:s');
    //             $newOrderItemModel->wholesal_id = $oOrderItemModel->wholesal_id;
    //             $newOrderItemModel->is_futures = 0;
    //             $newOrderItemModel->pending_quantity = $need_trans_quantity;
    //             $newOrderItemModel->is_advance = $oOrderItemModel->is_advance;
    //             $newOrderItemModel->advance_ratio = $oOrderItemModel->advance_ratio;

    //             $newOrderItemModel->transaction_currency_id = $oOrderItemModel->transaction_currency_id;
    //             $newOrderItemModel->price_selected_currency = $oOrderItemModel->price_selected_currency;
    //             $newOrderItemModel->purchase_currency = $item->purchase_currency;
    //             $newOrderItemModel->purchase_price = $item->purchase_price;

    //             if (!$newOrderItemModel->save()) {
    //                 return ['code' => 1, 'message' => '订单转换库存失败'];
    //             }
    //         }
    //         // 扣减库存
    //         foreach ($InventoryArr as $item) {
    //             foreach ($param['list'] as $jer) {
    //                 if ($item['id'] == $jer['id']) {
    //                     $item->available_qty = $item->available_qty - $jer['quantity'];
    //                     if (!$item->save()) {
    //                         return ['code' => 1, 'message' => '订单转换库存失败'];
    //                     }
    //                 }
    //             }
    //         }
    //         Db::commit();
    //     } catch (Exception $e) {
    //         Db::rollback();
    //         return ['code' => 1, 'message' => $e->getMessage()];
    //     }
    //     return ['code' => 0, 'message' => '订单转换库存成功'];
    // }
    /**
     * 订单转换库存
     * @param $param
     * @return array|void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * 2024-12-25 18 39 01
     * author: jiang
     */
    public function transSaveByWholesal($param)
    {
        $inventoryLogic = new InventoryTransSave();
        return $inventoryLogic->transSaveByWholesal($param);
        // Db::startTrans();
        // try {
        //     $oOrderItemModel = WholesalOrderItem::where('is_futures', '<>', 0)->find($param['id']);
        //     if (!$oOrderItemModel) {
        //         return ['code' => 1, 'message' => '未找到订单信息！'];
        //     }
        //     // 计算需要转换的总数量
        //     $need_trans_quantity = array_sum(array_column($param['list'], 'quantity'));

        //     // 查询可转换数量
        //     $where = [
        //         ['productid', '=', $param['productid']],
        //         ['arrival_date', '=', null],
        //         ['is_futures', '=', 0],
        //         ['is_del', '=', 0],
        //         ['id', 'in', array_column($param['list'], 'id')]
        //     ];

        //     $warehouse = WarehouseModel::where('id', '=', $param['wid'])->field('fl_warehouse_id')->find();
        //     if ($warehouse['fl_warehouse_id'] != null) {
        //         $where[] = ['wid', '=', $param['wid']];
        //     } else {
        //         $warehouse_ids = WarehouseModel::where('fl_warehouse_id', '=', $param['wid'])->column('id');
        //         $where[] = ['wid', 'in', $warehouse_ids];
        //     }
        //     $available_qty = 0;
        //     $InventoryArr = InventoryModel::where($where)
        //         ->whereRaw('(available_qty - lock_qty) > ?', [0])
        //         ->field([
        //             'available_qty - lock_qty as available_qty',
        //             'id',
        //             'purchase_currency',
        //             'purchase_price',
        //             'wid'
        //         ])
        //         ->select()
        //         ->toArray();
        //     $InventoryArr = array_column($InventoryArr, null, 'id');
        //     $newOrderItemModel = new WholesalOrderItem();
        //     foreach ($param['list'] as $jer) {
        //         $inventory = $InventoryArr[$jer['id']];


        //         if ($inventory['available_qty'] < $jer['quantity']) {
        //             throw new Exception('库存不足');
        //         } else {
        //             $resultUpdateOrderItem = $newOrderItemModel
        //                 ->where('id', $param['id'])
        //                 ->bind([
        //                     'dec_num1' => intval($jer['quantity']),
        //                     'dec_num2' => intval($jer['quantity'])
        //                 ])
        //                 ->update([
        //                     'pending_quantity' => Db::raw('pending_quantity - :dec_num1'),
        //                     'quantity' => Db::raw('quantity - :dec_num2'),
        //                 ]); // 原始订单明细减少
        //             if (!$resultUpdateOrderItem) {
        //                 throw new Exception('订单转换原始明细数据扣减失败');
        //             }

        //             $resultInsert = $newOrderItemModel->insert([
        //                 'user_id' => $oOrderItemModel->user_id,
        //                 'order_id' => $oOrderItemModel->order_id,
        //                 'product_id' => $oOrderItemModel->product_id,
        //                 'warehouse_id' => $inventory['wid'],
        //                 'original_price' => $oOrderItemModel->original_price,
        //                 'actual_price' => $oOrderItemModel->actual_price,
        //                 'quantity' => $jer['quantity'],
        //                 'creator' => $oOrderItemModel->creator,
        //                 'create_time' => date('Y-m-d H:i:s'),
        //                 'is_futures' => 0,
        //                 'pending_quantity' => $jer['quantity'],
        //                 'is_advance' => $oOrderItemModel->is_advance,
        //                 'advance_ratio' => $oOrderItemModel->advance_ratio,
        //                 'transaction_currency_id' => $oOrderItemModel->transaction_currency_id,
        //                 'price_selected_currency' => $oOrderItemModel->price_selected_currency,
        //                 'purchase_currency' => $inventory['purchase_currency'],
        //                 'purchase_price' => $inventory['purchase_price'],
        //                 'free_shipping' => $oOrderItemModel->free_shipping,
        //                 'apply_rules' => $oOrderItemModel->apply_rules
        //             ]);
        //             if (!$resultInsert) {
        //                 throw new Exception('订单转换库存插入订单明细失败');
        //             }
        //             $resultUpdateInventory = InventoryModel::where('id', $inventory['id'])
        //                 ->whereRaw('available_qty - lock_qty >= :min_qty')
        //                 ->bind([
        //                     'min_qty' => intval($jer['quantity']),
        //                     'dec_num' => intval($jer['quantity'])
        //                 ])
        //                 ->update([
        //                     'lock_qty' => Db::raw('lock_qty + :dec_num'),
        //                     'update_time' => date('Y-m-d H:i:s')
        //                 ]);
        //             if (!$resultUpdateInventory) {
        //                 throw new Exception('订单库存类型转换库存锁定失败');
        //             }
        //             $inventoryService = new InventoryService();
        //             $unlock = $inventoryService->unlockInventory([[
        //                 'product_id' => $oOrderItemModel->product_id,
        //                 'arrival_date' => $oOrderItemModel->arrival_date,
        //                 'is_futures' => $oOrderItemModel->is_futures,
        //                 'wid' => $oOrderItemModel->warehouse_id,
        //                 'quantity' => $jer['quantity'],
        //             ]]);
        //             if (!$unlock) {
        //                 throw new Exception('订单库存类型转换库存解锁失败');
        //             }
        //             $need_trans_quantity = $need_trans_quantity - $jer['quantity'];
        //         }
        //     }
        //     if ($need_trans_quantity > 0) {
        //         throw new Exception('库存不足');
        //     }
        //     Db::commit();
        // } catch (Exception $e) {
        //     Db::rollback();
        //     return ['code' => 1, 'message' => $e->getMessage()];
        // }
        // return ['code' => 0, 'message' => '订单转换库存成功'];
    }

    /**
     * 提篮子商品保存
     * @param $param
     * @return array|void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * 2025-02-25 17 14 14
     * author: jiang
     */
    public function baskets($param)
    {
        // 判断商品是否存在
        $oProduct = ProductModel::where('id', $param['productid'])->where('status', 1)->find();
        if (!$oProduct) {
            return ['code' => 1, 'message' => '商品不存在'];
        }
        Db::startTrans();
        try {
            // 新建库存
            $oInventoryModel = new InventoryModel();
            $oInventoryModel->productid = $param['productid'];
            $oInventoryModel->wid = $param['wid'];
            $oInventoryModel->source_table = 'inventory';
            $oInventoryModel->source_id = 0;
            $oInventoryModel->initial_qty = $param['available_qty'] ?? 0;
            $oInventoryModel->convertible_qty = 0;
            $oInventoryModel->available_qty = $param['available_qty'] ?? 0;
            $oInventoryModel->lock_qty = 0;
            $oInventoryModel->arrival_date = empty($param['arrival_date']) ? null : $param['arrival_date'];
            $oInventoryModel->real_arrival_date = empty($param['arrival_date']) ? null : $param['arrival_date'];
            $oInventoryModel->inbound_batch = 'TLZ.' . date('YmdHis');
            $oInventoryModel->is_futures = $param['is_futures'];
            $oInventoryModel->is_sale = $param['is_sale'];
            $oInventoryModel->creator = $param['operator_id'];
            $oInventoryModel->create_time = date('Y-m-d H:i:s');
            $oInventoryModel->remark = '提篮子商品报价';
            $oInventoryModel->allow_zero_stock_sale = 1;
            $oInventoryModel->if_tlz = 1;
            $oInventoryModel->ccname_ids = implode(',', $param['ccname_ids']);
            if (!$oInventoryModel->save()) {
                throw new Exception("库存保存失败！");
            }
            Db::commit();
        } catch (Exception $e) {
            Db::rollback();
            return ['code' => 1, 'message' => $e->getMessage()];
        }
        // 保存价格
        $batchWhere = [['productid', '=', $oInventoryModel->productid], ['wid', '=', $oInventoryModel->wid], ['arrival_date', '=', $oInventoryModel->arrival_date], ['is_futures', '=', $oInventoryModel->is_futures]];
        $batchIds = InventoryModel::where($batchWhere)->column('id');
        ProductPriceModel::where([['inventory_id', 'in', $batchIds], ['wid', '=', $oInventoryModel->wid]])->delete(); // 独立于事务外 后需要修正
        foreach ($param['product_prices'] as $value) {
            $arguments = [
                'id' => $oInventoryModel->id,
                'wid' => $oInventoryModel->wid,
                'is_sale' => $param['is_sale'],
                'operator_id' => $param['operator_id'],
                'currency' => $value['currency_id'],
                'sales_price' => $value['price'],
                'discount' => $value['discount']
            ];

            $result = $this->savePrice($arguments);
        }
        $this->clearCTerminalCache(6); // 清除C端产品缓存
        return ['code' => 0, 'message' => '保存成功'];
    }
    public function transferList($param)
    {
        $field = [
            'lo.logistics_no',
            'lo.company_id',
            'lo.notes',
            'lo.create_time',
            'lo.ship_date',
            'lo.id',
            'lo.cost',
            'lo.status',
            'lo.arrival_date',
            'lo.real_arrival_date',
            'lo.serial_number',
            'lo.transaction_currency_id',
        ];
        // 主查询条件（直接对lo表的条件）
        $mainWhere = [];
        $mainWhere[] = ['lo.type', 'in', [2, 3]];  // 这是对lo表的条件
        // 构建子查询的WHERE条件
        $subWhere = [];
        if ($param['product_id'] != null) {
            $subWhere[] = ['product_id', '=', $param['product_id']];
        }
        if ($param['serial_number'] != null) {
            $mainWhere[] = ['lo.serial_number', '=', $param['serial_number']];
        }
        if ($param['old_wid'] != null) {
            $subWhere[] = ['warehouse_id', '=', $param['old_wid']];
        }
        if ($param['new_wid'] != null) {
            $subWhere[] = ['to_warehouse_id', '=', $param['new_wid']];
        }
        // 现在，构造主查询
        $model = Db::table('db_logistics_order')
            ->alias('lo')
            ->field($field)
            ->where($mainWhere)  // 这里已经有 lo.type=2
            ->whereExists(function ($query) use ($subWhere) {
                // 子查询：从db_logistics_order_item表，关联条件是logistics_order_id等于主表的lo.id
                $query->table('db_logistics_order_item')
                    ->where('logistics_order_id', '=', 'lo.id')  // 使用表达式，直接写等于主表的id
                    ->where($subWhere);
            });
        // 另外，如果提供了logistics_no，则加入主查询条件
        if ($param['logistics_no'] != null) {
            $model->where('lo.logistics_no', '=', $param['logistics_no']);
        }
        if ($param['start_time'] != null) {
            $param['start_time'] = date("Y-m-d 00:00:00", strtotime($param['start_time']));
            $model->where('lo.create_time', '>=', $param['start_time']);
        }
        if ($param['end_time'] != null) {
            $param['end_time'] = date("Y-m-d 23:59:59", strtotime($param['end_time']));
            $model->where('lo.create_time', '<=', $param['end_time']);
        }

        $total = $model->count();
        // 如果总数为0，直接返回
        if (!$total) {
            return ['code' => 0, 'message' => '成功', 'data' => ['total' => 0, 'list' => []]];
        }
        // 否则，继续分页查询
        $result = $model->page($param['pageIndex'], $param['pageSize'])
            ->order('lo.id desc')
            ->select()
            ->toArray();
        $companyMedel = new \app\admin\model\LogisticsCompany();
        $company_ids = array_column($result, 'company_id');
        $company =  $companyMedel->whereIn('id', $company_ids)->field("id,name")
            ->select()->toArray();
        $company = array_column($company, null, 'id');
        foreach ($result as &$value) {
            if ($value['cost']) {
                $value['cost'] = json_decode($value['cost']);
            }
            $value['status_value'] = (new \app\admin\model\LogisticsOrder())->getAttributes('status')[$value['status']] ?? '';
            $value['company_name'] = '';
            if ($value['company_id']) {
                $value['company_name'] = $company[$value['company_id']]['name'] ?? '';
            }
        }

        return ['code' => 0, 'message' => '成功', 'data' => ['total' => $total, 'list' => $result]];
    }

    public function storage($param)
    {
        #参数校验
        if (!$param['id'] || !$param['arrival_batch']) {
            return ['code' => 1, 'message' => '参数错误'];
        }
        try {
            $logistics_order_iterm = LogisticsOrderItem::where('logistics_order_id', $param['id'])->field('number,to_warehouse_id as currentWId ,to_inventory_id as id')
                ->select()->toArray();
            if ($logistics_order_iterm) {
                foreach ($logistics_order_iterm as $item) {
                    $detail = $this->getOrderByInventory($item);
                    $list = [];
                    $inventory = \app\admin\model\Inventory::where('id',$item['id'])->find();
                    if(isset($inventory->convertible_qty)  && $inventory->convertible_qty >0){
                        $params = [
                            'operator_id' => $param['operator_id'],
                            'arrival_batch' => $param['arrival_batch'],
                            'convertible_qty' => $inventory->convertible_qty,
                            'futures' => 0,
                            'intoWarehouse' => null,
                            'id' => $item['id'],
                        ];
                        if ($detail['data']) {
                            foreach ($detail['data'] as $d) {
                                $list[] = [
                                    'id' => $d['order_id'],
                                    'type' => $d['type'],
                                    'num' => $d['num'],
                                ];
                            }
                        }
                        $params['list'] = $list;
                        $return = $this->transSave($params);
                        if ($return['code'] != 0) {
                            throw new Exception($return['message']);
                        }
                    }

                    unset($param['operator_id']);
                    unset($param['arrival_batch']);
                    $update =  $this->transferUpdate($param);
                    if ($update['code'] != 0) {
                        throw new Exception($update['message']);
                    }
                    $this->logger->logOperation($item['id'], 'inventory', '库存-调拨入库', '库存-调拨入库',1,'logistics_order',$param['id']);

                }
            }
            return ['code' => 0, 'message' => '调拨入库成功',];
        } catch (\Exception $e) {

            return ['code' => 1, 'message' => 'line.' . $e->getLine() . ' ' . $e->getMessage()];
        }
    }
    public function delay($param)
    {
        #参数校验
        if (!$param['id'] || !$param['real_arrival_date']) {
            return ['code' => 1, 'message' => '参数错误'];
        }
        try {
            \app\admin\model\LogisticsOrder::where('id', $param['id'])->update([
                'real_arrival_date' => $param['real_arrival_date']
            ]);
            $logistics_order_iterm = LogisticsOrderItem::where('logistics_order_id', $param['id'])->field('to_inventory_id')
                ->select()->toArray();
            if ($logistics_order_iterm) {
                foreach ($logistics_order_iterm as $item) {
                    InventoryModel::where('id', $item['to_inventory_id'])->update([
                        'real_arrival_date' => $param['real_arrival_date'],
                        'updater'   => $param['operator_id']
                    ]);
                    $this->logger->logOperation($item['to_inventory_id'], 'inventory', '库存-调拨延期到仓', '库存-调拨延期到仓',1,'logistics_order',$param['id']);
                }
            }
            return ['code' => 0, 'message' => '延迟入库成功',];
        } catch (\Exception $e) {

            return ['code' => 1, 'message' => 'line.' . $e->getLine() . ' ' . $e->getMessage()];
        }
    }

    public function transferDetail($id)
    {
        #参数校验
        if (!$id) {
            return ['code' => 1, 'message' => 'id不能为空'];
        }
        $logistics_order = \app\admin\model\LogisticsOrder::where('id', $id)
            ->field("id,company_id,ship_date,logistics_no,logistics_voucher,notes,arrival_date,real_arrival_date,serial_number,status,cost,transaction_currency_id,create_time")->find()->toArray();
        $logistics_voucher = explode(',', $logistics_order['logistics_voucher']);

        $logistics_order['company_name'] = '';
        $logistics_order['status_value'] = (new \app\admin\model\LogisticsOrder())->getAttributes('status')[$logistics_order['status']] ?? '';
        if ($logistics_order['company_id']) {
            $company =  \app\admin\model\LogisticsCompany::where('id', $logistics_order['company_id'])
                ->find();
            $logistics_order['company_name'] = $company->name ?? '';
        }
        $logistics_order['company_id'] = $logistics_order['company_id'] ==0?null:$logistics_order['company_id'];
        $logistics_order['logistics_voucher_info'] = [];
        $logistics_order['cost'] = $logistics_order['cost'] ? json_decode($logistics_order['cost']) : $logistics_order['cost'];
        if ($logistics_voucher) {
            #获取图片url
            $oImages = new \app\admin\model\Images();
            $photoUrls = $oImages->getImagesByIds($logistics_voucher);
            $avatorUrls = array_column($photoUrls, null, 'id');
            foreach ($logistics_voucher as $k => $v) {
                $url = $avatorUrls[$v]['url'] ?? '';
                if ($url) {
                    $logistics_order['logistics_voucher_info'][$k]['url'] = $url;
                    $logistics_order['logistics_voucher_info'][$k]['name'] = $avatorUrls[$v]['name'] ?? '';
                    $logistics_order['logistics_voucher_info'][$k]['id'] = $v;
                }
            }
        }

        $logistics_order_iterm =   LogisticsOrderItem::where('logistics_order_id', $id)->field('to_warehouse_id,warehouse_id,product_id,number,to_inventory_id as inventory_id')
            ->select()->toArray();

        $pids = array_column($logistics_order_iterm, 'product_id');
        $productInfo = ProductModel::whereIn('id', $pids)->field('id,cname')->select()->toArray();

        $inids = array_column($logistics_order_iterm, 'inventory_id');
        $inventoryInfo = InventoryModel::whereIn('id', $inids)->field('id,arrival_date')->select()->toArray();
        $wids = array_map(function ($iterm) {
            return [
                $iterm['warehouse_id'],
                $iterm['to_warehouse_id']
            ];
        }, $logistics_order_iterm);
        $wids = array_unique(array_merge([], ...$wids));
        $warehouseInfo = WarehouseModel::whereIn('id', $wids)->field('id,name')->select()->toArray();
        $warehouseInfo = array_column($warehouseInfo, null, 'id');
        $productInfo = array_column($productInfo, null, 'id');
        $inventoryInfo = array_column($inventoryInfo, null, 'id');
        foreach ($logistics_order_iterm as &$value) {
            $value['product_name'] = $productInfo[$value['product_id']]['cname'] ?? '';
            $value['warehouse_name'] = $warehouseInfo[$value['warehouse_id']]['name'] ?? '';
            $value['to_warehouse_name'] = $warehouseInfo[$value['to_warehouse_id']]['name'] ?? '';
            $value['arrival_date'] = $inventoryInfo[$value['inventory_id']]['arrival_date'] ?? '';
        }
        $logistics_order['iterm'] = $logistics_order_iterm;
        return ['code' => 0, 'message' => '成功', 'data' => $logistics_order];
    }
    /**
     * 更新
     * @param int $id 物流公司ID
     * @param array $data 更新物流公司的数据
     */
    public function transferUpdate($data)
    {
        $data['update_time'] = date('Y-m-d H:i:s');
        $oInventoryModel = new \app\admin\model\LogisticsOrder();
        $res = $oInventoryModel->where('id', $data['id'])->find();
        if (!isset($data['ship_date']) || empty($data['ship_date'])) {
            unset($data['ship_date']);
        }
        if (!$res) {
            return false;
        }
        foreach ($data as $key => $value) {
            if ('cost' == $key) {
                $value = json_encode($value);
            }
            if ($res->$key != $value) {
                $res->$key = $value;
            }
        }
        $result = $res->save();
        if ($result) {
            $this->logger->logOperation($res->id, 'transfer Inventory', '更新', '更新调拨物流信息成功');
            return ['code' => 0, 'message' => '更新成功'];
        } else {
            return ['code' => 1, 'message' => '更新失败'];
        }
    }
    /**
     * 库存调拨
     * @param $param
     * @return array|void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * 2025-02-25 17 14 14
     * author: jiang
     */
    public function transfer($param)
    {
        /**
         * 扣减原库存数量
         * 新增新库存
         * 生产物流记录
         *
         */
        if (!isset($param['productInfo']) || !$param['productInfo'] || !isset($param['company_id']) || !$param['company_id']) {
            return ['code' => 1, 'message' => '参数错误 '];
        }
        $oInventoryModel = new InventoryModel();
        $success = 0;
        $fail = 0;
        #数据校验
        foreach ($param['productInfo'] as $product) {
            $inventoryInfo = $oInventoryModel::where('id', $product['inventory_id'])->find()->toArray();
            $new_available_qty = $inventoryInfo['available_qty'] - $product['num'];
            if ($inventoryInfo['available_qty'] <= $inventoryInfo['lock_qty'] || $new_available_qty - $inventoryInfo['lock_qty'] < 0 || $inventoryInfo['is_futures'] != 0) {
                ++$fail;
                Log::error("库存调拨报错 可用库存不足或者商品不是现货 id: " . $product['inventory_id'] . " ,数量： " . $product['num']);
                continue;
            }
            if ($inventoryInfo['wid'] == $param['wid']) {
                ++$fail;
                Log::error("库存调拨报错 不能同仓库调拨");
                continue;
            }
            ++$success;
        }
        if ($success) {
            $success = 0;
            Db::startTrans();
            #新增物流订单记录
            $insertLogisticOrder = $this->insertLogisticOrderData($param);
            foreach ($param['productInfo'] as $value) {
                $inventoryInfo = $oInventoryModel::where('id', $value['inventory_id'])->find()->toArray();
                try {

                    $new_available_qty = $inventoryInfo['available_qty'] - $value['num'];
                    $new_initial_qty = $inventoryInfo['initial_qty'] - $value['num'];
                    if ($inventoryInfo['available_qty'] <= $inventoryInfo['lock_qty'] || $new_available_qty - $inventoryInfo['lock_qty'] < 0 || $inventoryInfo['is_futures'] != 0) {
                        ++$fail;
                        Log::error("库存调拨报错 可用库存不足或者商品不是现货");
                        continue;
                    }
                    $update_num = $oInventoryModel::where('id', $value['inventory_id'])->whereRaw(' available_qty - lock_qty  >= '.$value['num'])->dec('available_qty',$value['num'])->dec('initial_qty',$value['num'])->update();
                    if (!$update_num) {
                        ++$fail;
                        Log::error("库存调拨报错 可用库存不足");
                        continue;
                    }

                    #新增库存记录
                    $insertInventory = $this->insertInventoryData($inventoryInfo, $param, $value);
                    #新增库存变更记录
                    $insertInventoryChange = $this->insertInventoryChanggeData($param, $value, '库存调拨', '库存调拨');
                    #新增物流订单明细记录
                    $insertLogisticOrderIterm = $this->insertLogisticOrderItermData($inventoryInfo, $param, $value, $insertLogisticOrder, $insertInventory);
                    Db::commit();
                    $this->logger->logOperation($inventoryInfo->id, 'inventory', '库存-调拨发起', '库存-调拨发起',1,'logistics_order',$insertLogisticOrder->id);

                    ++$success;
                } catch (Exception $e) {
                    Db::rollback();
                    ++$fail;
                    Log::error("库存调拨报错: " . $e->getMessage() . ', line: ' . $e->getLine());
                }
            }
        }
        return ['code' => 0, 'message' => '操作成功', 'data' => ['success' => $success, 'fail' => $fail]];
    }
    public function cancelTransfer($param)
    {
        Db::startTrans();
        try {
            // 1. 验证调拨单有效性
            $logisticsOrder = \app\admin\model\LogisticsOrder::where('creator',$param['operator_id'])->find($param['id']);
            if (!$logisticsOrder || $logisticsOrder->status == 2) {
                throw new Exception("调拨单不存在或已被取消");
            }

            // 2. 获取调拨明细
            $orderItems = \app\admin\model\LogisticsOrderItem::where('logistics_order_id', $param['id'])->select();
            if (empty($orderItems)) {
                throw new Exception("调拨单无明细数据");
            }

            // 3. 循环还原每个商品
            $purchase_order = 0;
            foreach ($orderItems as $item) {
                #普通调拨单 归还库存
                if ($logisticsOrder['type'] == 2) {
                    /* 逆向操作1：恢复源库存 */
                    $sourceInventory = InventoryModel::find($item->inventory_id);
                    if ($sourceInventory) {
                        InventoryModel::where('id',$item->inventory_id)->inc('available_qty',$item->number)->inc('initial_qty',$item->number)->update() ; // 增加原库存数量

                        // 记录库存变更（恢复）
                        $this->insertInventoryChanggeData(
                            $param,
                            ['inventory_id' => $item->inventory_id, 'num' => $item->number],
                            '调拨取消',
                            '恢复源库存'
                        );
                    }
                }


                /* 逆向操作2：删除目标库存 */
                $targetInventory = InventoryModel::find($item->to_inventory_id);
                if ($targetInventory) {
                    // 检查目标库存是否被使用 [3,8](@ref)
                    if ($targetInventory->lock_qty > 0 || $targetInventory->available_qty != $item->number) {
                        $order_param = [
                            'id' => $item->to_inventory_id,
                            'currentWId' => $item->to_warehouse_id
                        ];
                        $detail = $this->getOrderByInventory($order_param);
                        if ($detail['data']) {
                            foreach ($detail['data'] as $orderList) {
                                OrderItemModel::where([
                                    'order_id' => $orderList['order_id'],
                                    'product_id' => $targetInventory->productid,
                                    'warehouse_id' => $targetInventory->wid,
                                    'arrival_date' => $targetInventory->arrival_date,
                                    'is_futures' => $targetInventory->is_futures

                                ])->update(['exceptionstatus' => 1]);

                                $oOrderModel =  \app\admin\model\Order::where(['id' => $orderList['order_id']])->find();
                                if ($oOrderModel->exceptionstatus) {
                                    $exceptionstatus = explode(',', $oOrderModel->exceptionstatus);
                                    if (!in_array(1, $exceptionstatus)) {
                                        array_push($exceptionstatus, 1);
                                        $oOrderModel->exceptionstatus = implode(',', $exceptionstatus);
                                    }
                                } else {
                                    $oOrderModel->exceptionstatus = 1;
                                }
                                $oOrderModel->save();

                                $orderPartnerNew = $oOrderModel->partner ? array_filter(explode(',', $oOrderModel->partner)) : [];
                                $recipients = array_filter(array_unique([$oOrderModel->owner,  $oOrderModel->signatory, ...$orderPartnerNew]));
                                $notificationService = new CompleteNotificationService();
                                $notificationService->send('order_exceptionstatus', $oOrderModel->toArray(), $recipients);
                            }
                        }
                    }
                    InventoryModel::where('id', $item->to_inventory_id)->update(['is_del' => time()]); // 物理删除目标库存

                    // 记录库存变更（删除）
                    $this->insertInventoryChanggeData(
                        $param,
                        ['inventory_id' => $item->to_inventory_id, 'num' => -$item->number],
                        '调拨取消',
                        '删除目标库存'
                    );
                }
                #采购单生成的调拨单 需要归还入库 修改采购单的状态
                if ($logisticsOrder['type'] == 3) {
                    if ($item->order_id) {
                        #入库 删除
                        $purchase_order = $item->order_id;
                        PurchaseReceiptDetails::where('id', $item->order_id)->update(['is_del' => time()]);
                    }
                }
                $this->logger->logOperation($item->to_inventory_id, 'inventory', '库存-调拨撤销', '库存-调拨撤销',1,'logistics_order',$logisticsOrder->id);

            }

            // 4. 更新调拨单状态 [1,2](@ref)
            $logisticsOrder->status = 2; // 2=已取消
            $logisticsOrder->save();
            #采购单生成的调拨单 需要归还入库 修改采购单的状态
            if ($logisticsOrder['type'] == 3) {
                $purchase_detail = PurchaseReceiptDetails::where('id', $purchase_order)->value('purchase_orders_detail_id');
                $purchase_order_id = PurchaseOrdersDetail::where('id', $purchase_detail)->value('orderid');
                PurchaseOrders::where('id', $purchase_order_id)->update(['status' => 30]);
            }
            Db::commit();

            return ['code' => 0, 'message' => '取消调拨成功'];
        } catch (Exception $e) {
            Db::rollback();
            return ['code' => 1, 'message' => '取消失败: ' . $e->getMessage()];
        }
    }
    public function insertInventoryData($inventoryInfo, $param, $value)
    {
        # 默认取仓库 可售国家分类
        if (!$param['cc_name_id']) {
            $warehouse = new WarehouseModel();
            $pwid = $warehouse->getTopLevelWarehouseId($param['wid']);
            $pwid = $pwid[0];
            $cc_name = Db::name('cc_names')->field('id')->where('is_del', 0)->whereRaw('FIND_IN_SET(?, sellable_wids)', [$pwid])->select()->toArray();
            if ($cc_name) {
                $cc_name = array_column($cc_name, 'id');
                $param['cc_name_id'] = implode(',', $cc_name);
            }
        }
        $new_inventory_base = [
            'productid' => $inventoryInfo['productid'],
            'purchase_currency' => $inventoryInfo['purchase_currency'],
            'purchase_price' => $inventoryInfo['purchase_price'],
            'if_tlz' => $inventoryInfo['if_tlz'],
            'ccname_ids' => $param['cc_name_id'],
            'wid' => $param['wid'],
            'remark' => $param['notes'],
            'creator' => $param['operator_id'],
            'create_time' => date("Y-m-d H:i:s"),
            'source_table' => 'inventory',
            'source_id' => $value['inventory_id'],
            'initial_qty' => $value['num'],
            'convertible_qty' => $value['num'],
            'available_qty' => $value['num'],
            'lock_qty' => 0,
            'is_sale' => $inventoryInfo['is_sale'],
            'is_del' => 0,
            'is_futures' => 1,
            'allow_zero_stock_sale' => $inventoryInfo['allow_zero_stock_sale'],
            'arrival_date' => $param['arrival_date'],
            'real_arrival_date' => $param['arrival_date'],
            'inbound_batch' => date('YmdHis') . mt_rand(1, 9999),
        ];
        $oInventoryModel = new InventoryModel();
        $newId = $oInventoryModel->insertGetId($new_inventory_base);;
        $this->insertInventoryPrice($inventoryInfo, $newId, $param['wid'], $param['operator_id']);
        return $newId;
    }
    public function insertInventoryPrice($inventoryInfo, $newId, $wid, $operator_id)
    {
        $partent_wid  = $inventoryInfo['wid'];
        $discount_insert = [];
        // 获取原有价格
        $oProductPriceModel = ProductPriceModel::with('discount')->where([
            ['inventory_id', '=', $inventoryInfo['id']],
            ['wid', '=', $partent_wid],
            ['is_del', '=', '0']
        ])->select();


        foreach ($oProductPriceModel as $item) {
            $newProductPriceModel = new ProductPriceModel();
            $newProductPriceModel->inventory_id = $newId;
            $newProductPriceModel->wid = $wid;
            $newProductPriceModel->transaction_currency_id = $item->transaction_currency_id;
            $newProductPriceModel->price = $item->price;
            $newProductPriceModel->first_leg_logistics_fee = $item->first_leg_logistics_fee;
            $newProductPriceModel->is_del = 0;
            $newProductPriceModel->creator = $operator_id;
            $newProductPriceModel->create_time = date('Y-m-d H:i:s');
            if (!$newProductPriceModel->save()) {
                throw new Exception("库存价格存储失败！");
            }
            if ($item->discount) {
                foreach ($item->discount as $discount) {
                    $discount_insert[] = [
                        'price_id' => $newProductPriceModel->id,
                        'level' => $discount->level,
                        'num' => $discount->num,
                        'rate' => $discount->rate,
                        'price' => $discount->price,
                        'creator' => $operator_id,
                        'create_time' => date('Y-m-d H:i:s')
                    ];
                }
            }
        }

        if (count($discount_insert) > 0) {
            $discount_result = ProductDiscountModel::insertAll($discount_insert);
            if (!$discount_result) {
                throw new Exception("库存折扣存储失败！");
            }
        }
    }
    public function insertInventoryChanggeData($param, $value, $business, $remark)
    {
        $inventory_change_base = [
            'inventory_id' => $value['inventory_id'],
            'business_tabel_name' => 'inventory',
            'business_table_id' => $value['inventory_id'],
            'business' => $business,
            'remark' => $remark,
            'number' => $value['num'],
            'creator' => $param['operator_id'],
            'create_time' => date("Y-m-d H:i:s"),
        ];
        $oInventoryModel = new InventoryChangeRecord();
        return $oInventoryModel->insertGetId($inventory_change_base);
    }
    public function insertLogisticOrderData($param, $type = 2)
    {
        $logistics_order_base = [
            'serial_number' => $dateCode = date('ymd', time()) . mt_rand(111111, 999999),
            'company_id' => $param['company_id'],
            'arrival_date' => $param['arrival_date'],
            'real_arrival_date' => $param['arrival_date'],
            'logistics_no' => $param['logistics_no'],
            'logistics_voucher' => $param['logistics_voucher'],
            'cost' => json_encode($param['cost']),
            'notes' => $param['notes'],
            'creator' => $param['operator_id'],
            'transaction_currency_id' => $param['transaction_currency_id'],
            'create_time' => date("Y-m-d H:i:s"),
            'ship_date' => empty($param['ship_date']) ? null : $param['ship_date'],
            'type' => $type,

        ];
        $oInventoryModel = new \app\admin\model\LogisticsOrder();
        return $oInventoryModel->insertGetId($logistics_order_base);
    }
    public function insertLogisticOrderItermData($inventoryInfo, $param, $value, $insertLogisticOrder, $insertInventory)
    {
        $logistics_order_iterm_base = [
            'logistics_order_id' => $insertLogisticOrder,
            'product_id' => $inventoryInfo['productid'],
            'warehouse_id' => $inventoryInfo['wid'],
            'number' => $value['num'],
            'to_warehouse_id' => $param['wid'],
            'create_time' => date("Y-m-d H:i:s"),
            'inventory_id' => $value['inventory_id'],
            'to_inventory_id' => $insertInventory,
        ];
        $oInventoryModel = new \app\admin\model\LogisticsOrderItem();
        return $oInventoryModel->insertGetId($logistics_order_iterm_base);
    }
}
